Search code examples
phpcomposer-phpautoloadpsr-4

Composer autoload not working for package with custom installer-paths set


Main project

I have a project setup with this main composer.json, requiring a custom plugin to a custom install path:

{
    "name": "myself/main-project",
    "repositories": [
        { 
            "type": "git", 
            "url": "https://github.com/myself/some-plugin.git" 
        }
    ],
    "require": {
        "myself/some-plugin": "@dev",
    },
    "extra": {
        "installer-paths": {
            "some-other-path/{$name}/": ["type:wordpress-plugin"]
        }
    }
}

The plug-in

The plugin has a separate repo and has a composer.json something like this, with autoloading namespace Foo:

{
    "name": "myself/some-plugin",
    "type": "wordpress-plugin",
    "autoload": {
        "psr-4": {
            "Foo\\": "src"
        }
    },
    "require": {
        "composer/installers": "^2.1"
    }
}

The plugin has a namespaced class Bar in src/Bar.php:

<?php

namespace Foo;

class Bar {
  public function __construct() {
    echo 'Foobar!';
  }
}

The problem

Autoloading doesn't seem to work when the plugin is installed in a custom path. Somewhere else in the program I try to call the class Bar:

<?php

require_once(dirname(__DIR__) . '/vendor/autoload.php');

$bar = new Foo\Bar();

Which gives me the error Fatal error: Uncaught Error: Class "Foo\Bar" not found.

But if I change the custom installer-paths in the main composer.json to the normal vendor folder and reinstall:

"installer-paths": {
    "vendor/{$name}/": ["type:wordpress-plugin"]
}

...everything works as expected and I get a Foobar! from the class.

What I've tried

  • Checking if autoloader picks up on the Foo namespace in the generated files, it does.
  • Loading the plugin locally with composer's path ("type": "path"), same problem.
  • Trying to load from \Foo\Bar and all other combinations.

Why is autoloading behaving unexpected when a custom installer-path is set?


Solution

  • I overlooked something, and this turned out not to be a problem with composer. The path to the vendor directory was not the same on my local disk vs inside the docker container.