Autoloading With Composer

Namespaces are a very nice feature that allows you to organise your code so that you can encapsulate classes and libraries and avoid clashes.

One of the problems with namespaces in PHP is that you still need to somehow load the physical files that contain the classes with require and include. So you have to make sure that you are including the appropriate files globally before using the namespaces.

There are some solutions to this. It is very common to see a global bootstrap file that simply includes all of the files. Then, you are free to use the namespaces anywhere. But this means you have to ensure that you have included them here and maintain this list every time you want to create a new class or namespace.

The better solution is to use the PHP spl_autoload_register. This allows you to put together a function that takes namespaces and dictate where to find the files.

Instead of implementing this function myself, I used to use Symfony's ClassLoader. This basically had a great implementation for auto loading. I still had to register the autoloader in a bootstrap file but at least I no longer have a list of files to include.

But this class is now deprecated and soon to be removed. Even so, there is actually an even easier way of dealing with this problem using Composer.

If you are not using Composer to manage your external dependencies already, then you really should be. I wrote a quick guide to get you started.

When you install libraries using composer, you have a single file that when included, will auto load all of the libraries installed. So 1 include can potentially load hundreds of libraries automatically. But, this doesn't have to be limited to external libraries. In this post, I will show you how you can add your own folders to this autoloader and then you can say goodbye to complex bootstrap files!

PSR-4

If you were already using any kind of autoloading that didn't involve manually including every single file, you probably already were using some kind of convention for the folder structure to ensure an easy translation to from namespace to directory path.

You may even be using the industry standard described by PHP-FIG in the form of PSR-4. You can read all about here. If you are not, you really should be and you will need to for this to work.

To sum up, you have a base namespace prefix e.g.

My\Namespace 

Which gets mapped to a base location e.g.

special_project/src/

Then when you use a fully qualified class name e.g.

\My\Namespace\Library\Class

The folder structure and file names must be the same inside the base location as they are after the namespace prefix. So in this case it Class would have to be in:

special_project/src/Library/Class.php

I hope that sort of makes sense. The official webpage explains it a lot clearer I think.

If you were using the Symfony ClassLoader component, then you were already doing this probably. Even if you were doing your own thing, it was probably pretty close to this as it makes a lot of sense.

Using Composer

I am going to assume that at this point you are familiar with Composer and how to use it to install external libraries.

Inside the composer.json file, under all of your dependencies, simply add (using the above example):

"autoload": {
    "psr-4": {"My\\Namespace\\": "special_project/src/"}
}

You can see that you are specifying that you wish to use the PSR-4 standard and what the namespace prefix path is and the base location. Note that base location is from inside the same location as the vendor folder.

When you run the composer update (or install if its the first time), you simply have to include the autoload.php that is inside vendor (which, if you are already using composer, you are already doing this) and that's it: you are free to use the namespace. You can also run composer dumpautoload -o to avoid updating all of your external libraries.

You can do multiple namespaces too of course:

"autoload": {
    "psr-4": {
        "My\\Namespace\\": "special_project/src/",
        "Brand\\": "lib/"
    }
}

Simple!

This way gets rid of a lot of unnecessary code and is heavily optimised as you are letting composer do the work for you!


© 2012-2023