4

I developed a small library for internal use within my company and some of our clients. This library was developed on a PHP 7 environment.

It has been installed and used successfully on my colleagues' computers and some of my clients severs running PHP 7 (including 7.0 and 7.1). Recently I came across a client on a shared hosting platform running PHP 5.6, and composer could download and install the package without any errors, but does not autoload the classes, for example:

<?php
include "vendor/autoload.php";
use MyVendor\MyPackage\Client\ClientObject;
$client = new ClientObject();
// PHP 7 : OK
// PHP 5 : PHP Fatal Error: Cannot find class MyVendor\MyPackage\Client\.....

Runs fine on PHP 7 environments but not PHP 5. I thought it could be the shared hosting but I spun up a PHP 5 VM on my machine and verified that the autoloading does not work as well.

I inspected the vendor/composer directory and found that the files are exactly the same. The autoloading only fails for my package and not its dependencies such as GuzzleHttp, so it's proabbly something wrong with my package but I don't know what to look out for.

Addendum Directory structure for my package, when installed by composer:

- MyVendor
| - MyPackage
| | - src
| | | - client
| | | | - ClientObject.php
| | | - (other files and folders)
| | - composer.json

Autoloader defined in composer.json as "psr-4" : { "MyVendor\\MyPackage\\" : "src/" }

chesnutcase
  • 500
  • 2
  • 7
  • 20

1 Answers1

2

Answering my own question: It was not the PHP version, it was the case-insensitive filesystem.

It just so happened that the PHP7 environments that "worked" were on filesystems that were case-insensitive (NTFS,HFS+ etc), while the PHP5 environments were on case-sensitive ones like ext4. This includes shared/mounted folders on systems that would normally have case-sensitive filesystems such as linux filesystems, so I urge future readers to take extra caution with this.

As shown above, my folder names were not PSR4 compliant (must match exact case), but this will not flag any issues on a case-insensitive filesystem, regardless of PHP version. However it will break if you deploy your project anywhere else with case-sensitive filesystems.

Because you need to do git mv twice to capitalise folder names on a case-insensitive filesystem (like this), it can get tedious if your project already has alot of existing subfolders, so I'll leave this bash script here that does that automatically: (gist here)

#!/bin/bash
for i in `find src -type d | grep -v '^src$' | sort -r`; do
  if [[ ! -e "$i"2 ]]; then
    mkdir -p "$i"2
  fi
  echo "start"
  for j in `find $i -maxdepth 1 -type f`; do
    echo $(git mv "$j" "$i"'2')
  done
  i2=`echo $i | sed -e "s/\b\(.\)/\u\1/g" | sed -e "s/Src/src/g"`
  for j in `find $i'2' -maxdepth 1 -type f`; do
    echo $(git mv "$j" "$i2")
  done
done

for i in `find src -type d | grep -v '^src$'`; do
  i2=`echo $i | sed -e "s/\b\(.\)/\u\1/g" | sed -e "s/Src/src/g"`
  rename $i $i2 $i
done


find . -type d -empty -name "*2" -delete
chesnutcase
  • 500
  • 2
  • 7
  • 20