2
votes

So I'm working on a composer plugin that adds a custom command that can be run after an install or update.

I understand the autoloading configuration, and composer is autoloading all classes but it's also missing a file that just contains namespaced functions.

In my plugin composer.json I have the following:

{
    "name": "myco/composer-s3-downloader",
    "type": "composer-plugin",
    "version": "0.1",
    "require": {
        "composer-plugin-api": "1.1.*",
        "aws/aws-sdk-php": "3.20.*"
    },
    "autoload": {
        "psr-4": {"MyCo\\Composer\\": "MyCo/"}
    },
    "extra": {
        "class": "MyCo\\Composer\\S3Downloader"
    }
}

My plugin classes load without a problem. All of the classes for my dependencies also load without a problem. So my plugin command code starts off just fine using the AWS SDK.

The problems comes here, when I try to instantiate an S3Client:

private function initClient() {
   if (is_null($this->_s3Client)) {
        $this->_s3Client = new \Aws\S3\S3Client([
            "version" => "latest",
            "region" => 'us-west-2',
            "credentials" => [
            "key" => $this->_creds['key'],
            "secret" => $this->_creds['secret'],
            ]]);
    }
}

I get the following error:

PHP Fatal error: Call to undefined function Aws\manifest() in .../test/vendor/aws/aws-sdk-php/src/AwsClient.php on line 143

I can see the autoload config in the AWS composer.json and it's correct:

"autoload": {
    "psr-4": {
        "Aws\\": "src/"
    },
    "files": ["src/functions.php"]
}

The Aws\manifest function is declared in functions.php. And functions.php is then specified in vendor/composer/autoload_files.php. But near as I can tell that file isn't being loaded. So not all of my dependencies are actually available.

What step am I missing that forces the inclusion of autoload_files.php? I'm not doing a single include for anything in the vendor folder. I'm assuming that composer will handle that for me. But I guess I'm wrong.

1

1 Answers

2
votes

So after posting an issue at the Composer Github repo, I did learn that the autoloader that runs during composer execution only includes classes. So if you do need to include loose functions, you'll have to manually run the full autoloader.

I added the following method to my Command class that is loaded by composer and defined in the extra section of the plugin's composer.json.

private function getIncludes() {
    $vendorDir = $this->composerInstance->getConfig()->get('vendor-dir');
    require $vendorDir . '/autoload.php';
}

I just call it in my plugin constructor and everything I need becomes available.