(Relevant files linked at the bottom of my question.)
I let Composer run some post-install-cmd
and post-update-cmd
scripts. In my script I want to make use of the readlink()
function from symfony/filesystem
. Inside my projects /vendor
folder there is the 3.4
version of the filesystem package, fine.
I use Symfony\Component\Filesystem\Filesystem;
at the top of my file.
But whenever I run:
$fs = new Filesystem();
$path = '/path/to/some/symlink';
if ($fs->readlink($path)) {
// code
}
I get the following error which tells me I'm calling an undefined method:
PHP Fatal error: Uncaught Error: Call to undefined method Symfony\Component\Filesystem\Filesystem::readlink() in /Users/leymannx/Sites/blog/scripts/composer/ScriptHandler.php:160
OK, so I double-checked the class inside my project's /vendor
folder. This method is there. My IDE points me there. But when I run:
$fs = new Filesystem();
get_class_methods($fs);
this method is not listed.
OK, so I tried to check which file it's loading this class from:
$fs = new Filesystem();
$a = new \ReflectionClass($fs);
echo $a->getFileName();
and that returns me phar:///usr/local/Cellar/composer/1.7.2/bin/composer/vendor/symfony/filesystem/Filesystem.php
– But why? Why is it taking the package from my Mac's Cellar? That's odd.
But OK, so I thought that's a Homebrew issue, and uninstalled the Homebrew Composer $ brew uninstall --force composer
and installed it again as PHAR like documented on https://getcomposer.org/doc/00-intro.md#globally.
But now it's the same.
$fs = new Filesystem();
$a = new \ReflectionClass($fs);
echo $a->getFileName();
returns me phar:///usr/local/bin/composer/vendor/symfony/filesystem/Filesystem.php
.
But why? Why does it pick up the (outdated) package from my global Composer installation? How can I force my script to use the project's local class and not the one from my global Composer installation?
Initially my $PATH
contained /Users/leymannx/.composer/vendor/bin /usr/local/bin /usr/bin /bin /usr/sbin /sbin
. I removed /Users/leymannx/.composer/vendor/bin
to only return /usr/local/bin /usr/bin /bin /usr/sbin /sbin
. Still the same.
I also tried setting the following in my composer.json
. Still the same:
"optimize-autoloader": true,
"classmap-authoritative": true,
"vendor-dir": "vendor/",
I finally created an issue on GitHub: https://github.com/composer/composer/issues/7708
Finally fixed it by requiring require_once __DIR__.'/../vendor/autoload.php'
at the top of my script and leaving everything else untouched.
On the Filesystem Component docs page it's also written:
If you install this component outside of a Symfony application, you must require the
vendor/autoload.php
file in your code to enable the class autoloading mechanism provided by Composer.