Using Composer's Autoload

PhpAutoloadComposer Php

Php Problem Overview


I have been looking around the net with no luck on this issue. I am using composer's autoload with this code in my composer.json:

"autoload": {
    "psr-0": {"AppName": "src/"}
}

But I need to autoload at a higher level than the vendor folder.

Doing something like this does not work:

"autoload": {
    "psr-0": {"AppName": "../src/"}
}

Does anyone know a fix or how I can do this?

Php Solutions


Solution 1 - Php

Every package should be responsible for autoloading itself, what are you trying to achieve with autoloading classes that are out of the package you define?

One workaround if it's for your application itself is to add a namespace to the loader instance, something like this:

<?php

$loader = require 'vendor/autoload.php';
$loader->add('AppName', __DIR__.'/../src/');

Solution 2 - Php

The composer documentation states that: > After adding the autoload field, you have to re-run install to > re-generate the vendor/autoload.php file.

Assuming your "src" dir resides at the same level as "vendor" dir:

  • src
  • AppName
  • vendor
  • composer.json

the following config is absolutely correct:

{
    "autoload": {
        "psr-0": {"AppName": "src/"}
    }
}

but you must re-update/install dependencies to make it work for you, i.e. run:

php composer.phar update

This command will get the latest versions of the dependencies and update the file "vendor/composer/autoload_namespaces.php" to match your configuration.

Also as noted by @Dom, you can use composer dump-autoload to update the autoloader without having to go through an update.

Solution 3 - Php

There also other ways to use the composer autoload features. Ways that can be useful to load packages without namespaces or packages that come with a custom autoload function.

For example if you want to include a single file that contains an autoload function as well you can use the "files" directive as follows:

"autoload": {
    "psr-0": {
        "": "src/",
        "SymfonyStandard": "app/"
    },
    "files": ["vendor/wordnik/wordnik-php/wordnik/Swagger.php"]
},

And inside the Swagger.php file we got:

function swagger_autoloader($className) {
	$currentDir = dirname(__FILE__);
	if (file_exists($currentDir . '/' . $className . '.php')) {
		include $currentDir . '/' . $className . '.php';
	} elseif (file_exists($currentDir . '/models/' . $className . '.php')) {
		include $currentDir . '/models/' . $className . '.php';
	}
}
spl_autoload_register('swagger_autoloader');

https://getcomposer.org/doc/04-schema.md#files

Otherwise you may want to use a classmap reference:

{
    "autoload": {
        "classmap": ["src/", "lib/", "Something.php"]
    }
}

https://getcomposer.org/doc/04-schema.md#classmap

Note: during your tests remember to launch the composer dump-autoload command or you won't see any change!

./composer.phar dump-autoload

Happy autoloading =)

Solution 4 - Php

In my opinion, Sergiy's answer should be the selected answer for the given question. I'm sharing my understanding.

I was looking to autoload my package files using composer which I have under the dir structure given below.

<web-root>
	|--------src/
	|			|--------App/
	|			|
	|			|--------Test/
	|
	|---------library/
	|
	|---------vendor/
	|			|
	|			|---------composer/
	|			|			|---------autoload_psr4.php
	|			|			
	|			|----------autoload.php
	|
	|-----------composer.json
	|

I'm using psr-4 autoloading specification.

Had to add below lines to the project's composer.json. I intend to place my class files inside src/App , src/Test and library directory.

"autoload": {
        "psr-4": {
            "OrgName\\AppType\\AppName\\": ["src/App", "src/Test", "library/"]
        }
    } 

This is pretty much self explaining. OrgName\AppType\AppName is my intended namespace prefix. e.g for class User in src/App/Controller/Provider/User.php -

namespace OrgName\AppType\AppName\Controller\Provider; // namespace declaration

use OrgName\AppType\AppName\Controller\Provider\User; // when using the class

Also notice "src/App", "src/Test" .. are from your web-root that is where your composer.json is. Nothing to do with the vendor dir. take a look at vendor/autoload.php

Now if composer is installed properly all that is required is #composer update

After composer update my classes loaded successfully. What I observed is that composer is adding a line in vendor/composer/autoload_psr4.php

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
	'OrgName\\AppType\\AppName\\' => array($baseDir . '/src/App', $baseDir . '/src/Test', $baseDir . '/library'),
);

This is how composer maps. For psr-0 mapping is in vendor/composer/autoload_classmap.php

Solution 5 - Php

Just create a symlink in your src folder for the namespace pointing to the folder containing your classes...

ln -s ../src/AppName ./src/AppName

Your autoload in composer will look the same...

"autoload": {
    "psr-0": {"AppName": "src/"}
}

And your AppName namespaced classes will start a directory up from your current working directory in a src folder now... that should work.

Solution 6 - Php

The autoload config does start below the vendor dir. So you might want change the vendor dir, e.g.

{
    "config": {
        "vendor-dir": "../vendor/"
    },
    "autoload": {
        "psr-0": {"AppName": "src/"}
    }
}

Or isn't this possible in your project?

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChris RView Question on Stackoverflow
Solution 1 - PhpSeldaekView Answer on Stackoverflow
Solution 2 - PhpSergiy SokolenkoView Answer on Stackoverflow
Solution 3 - PhpFrancesco CasulaView Answer on Stackoverflow
Solution 4 - PhpnayakView Answer on Stackoverflow
Solution 5 - PhpJamesHalsallView Answer on Stackoverflow
Solution 6 - PhpacmeView Answer on Stackoverflow