Skip to content

Jesses Software Engineering Blog

Sep 17

Jesse

PHP Composer Autoloading

Composer is PHP’s dependency manager tool. Composer allows you to specify libraries that are need for a project, and will automatically include those libraries along with their dependencies. Composer also allows you to create your own packages and share them via the Packagist website. Even when working on projects in which you are not using external dependencies, the use of the Composer autoloader can be beneficial not only for convenience but also in keeping your project standardized.

Installation

Composer is downloaded as an executable PHAR file. To download:

curl -sS https://getcomposer.org/installer | php

I like to move the file to my user’s PATH that way I can access from anywhere

mv composer.phar /usr/bin/composer
composer --version

All of the of your project’s dependencies are defined in a composer.json file. At a minimum you can just define an empty file:

{

}

To install your dependencies run:

composer install

Even without any defined dependencies in the JSON file, a vendor directory is created which is where all of your project dependencies are stored, as well as the Composer autoloader functionality.

Auto Loading Project Files

Composer autoloading provides a variety of different autoloading functionality, although it is recommended to use PSR 4 autoloading which is the default implementation.

To use PSR 4 autoloading, you simply have to follow a specific namespace convention. In general, you will create a src/ directory in your root folder, sitting at the same level as vendor/, and add your projects there. For example if you have a Vehicle project, you would make the folder structure src/Vehicle, and place your classes in there: src/Vehicle/Cars.php, etc. In your PHP file you would use: namespace Vehicle;. As you create a deeper folder structure, you just mirror the namespace to the directory structure. The following files would have these namespaces:

src/Vehicle/Road/Car.php			namespace Vehicle\Road;
src/Vehicle/Air/Wings/Airplane.php		namespace Vehicle\Air\Wings;
src/Book/History/UnitedStates.php		namespace Book\History;

In order for the Composer autoloading to be able to find your classes you need to define the src folder for your projects. You can do this by updating the composer.json file and running update:

{
    "autoload": {
        "psr-4": {
            "Vehicle\\": "src/Vehicle/",
	    "Book\\": "src/Book/"
        }
    }
}
composer update

Now when you need to use your project simply include the autoload.php file and import the namespaces you want to use:

require_once __DIR__ . '/vendor/autoload.php';

use \Vehicle\Road;
new Road\Car();

You can see the namespace registration in vendor/composer/autoload_psr4.php. This is where the namespace is actually linked to the directory structure. Note that your folders names are case sensitive and typically the first folder under src/ will be lowercase and the following folders camel cased: src/project/Vehicle/Road. Also, depending on your project, you may not want a different autoloader entry for each project folder.

This is just as an example of a common project set up, and you should be aware that there are different autoloading standards, as well as a lot of flexibility on how you set your project up.

Auto Loading Vendor Files

The autoloading for vendor files works pretty much the same as the autoloading for your own project files. If you have a project with dependencies, first add them to the composer.json file, and then run install (or update):

{
    "require": {
        "guzzlehttp/guzzle": "4.*",
        "monolog/monolog": "1.*"
    },
    "autoload": {
        "psr-4": {
            "Project\\": "src/Project/"
        }
    }
}

Now looking at the autoload_psr4.php file you can see the new namespaces and the directories that they are mapped to. So in order to use a Guzzle Client, simply:

require_once __DIR__ . '/vendor/autoload.php
$Client = new GuzzleHttp\Client();

Which we see is mapped to: vendor/guzzlehttp/guzzle/src

I will go into more detail when I discuss creating your own packages, but at this point you should feel confident enough to use vendor namespaces along with Composer autoloading.

Performance

One thing worth noting is that for large projects the overhead of using the Composer autoloader can become noticeable. This is partly due to the overhead incurred with a lot of file_exists() calls. One way to get around this is to convert the autoloader to use a class map using the dumpautoload command:

composer dumpautoload -o

This will create a map of all namespaces to their respective files. The downside to this approach is that every time new classes are introduced the class map would need to be re-created, as well as any time the composer install/update commands are ran. Another consideration, if you are using Zend’s opcache, is using the directive opcache.enable_file_override which also can help mitigate some of the overhead.

Conclusion

Composer is an extremely useful tool in dependency management, as well as provides standardized autoloading functionality. Composer offers a lot more functionality, and quickly became an industry standard for PHP dependency management.

Blog Powered By Wordpress