Ashley Sheridan​.co.uk

Creating your own classes that use the PSR-4 autoloader

Posted on

The PSR-4 standard has been around for quite a while now, building on and adding to the PSR-0 standard, allowing PHP to autoload classes using a cleaner and better organised file tree.

One thing I did notice is that not all the documentation on the autoloader is as clear as it could be with regards to how you would actually use it for your own new classes.

The first thing would be to get a PSR-4 autoloader, and the easiest way to do that is to use the one that Composer installs by default. If you already have Composer installed, you can jump to the last step:

# download, verify, and run installer as per https://getcomposer.org/download/ # ideally do this somewhere that's in the PATH, such as ~/bin php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" php -r "if (hash_file('SHA384', 'composer-setup.php') === 'aa96f26c2b67226a324c27919f1eb05f21c248b987e6195cad9690d5c1ff713d53020a02ac8c217dbf90a7eacc9d141d') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" php composer-setup.php php -r "unlink('composer-setup.php');" # rename the composer.phar and make it executable mv composer.phar composer chmod +x composer # initialise Composer in your PHP project directory and install the autoloader composer init composer install

From the composer init line, follow the prompts that guide you through setting up the initial project; usually you can hit enter to accept the default values for most questions.

You'll notice that it created a composer.json file in the root of your project. This is what you'll be modifying to inform Composer of where your classes live, as the PSR-4 standard doesn't map namespaces classes directly to file paths now.

In your project, let's imagine you want to create a class that creates small graphs as images. You might call this class file graph.php and namespace it in MyBlog\Images because it is a type of image class that belongs to your blog. Your directory structure would look like this:

Of course, you can lay out your directory structure however you wish, that's one of the key benefits of PSR-4.

You may be wondering what happened to the Images part of the namespace went. That goes into the graph.php file itself as the namespace:

<?php namespace MyBlog\Images; class Graph { // graph class code goes here }

At this point, your app still doesn't know about where to find this class, so if you attempt to use it with the following code, you will encounter an error:

<?php $loader = require __DIR__ . '/vendor/autoload.php'; // loads the Composer autoloader $graph = new MyBlog\Images\Graph();

The reason is that Composers autoload doesn't yet know about the class, so it isn't able to instruct your app what file to load. In order to get that part working, we need to modify our composer.json file with the path to our new class mapped against the namespace:

{ "name": "project name", "type": "project", "authors": [ { "name": "your name", "email": "your email" } ], "require": {}, "autoload": { "psr-4": { "MyBlog\\Images\\": "src/MyBlog/" } } }

The key section to pay attention to here is the autoload block, which tells Composer to use the PSR-4 autoloader for the following namespaces, and then you list each namespace followed by the directory path. It's worth noting that you don't have to specify the file path, just the directory, as in the future you may well want to add more classes under the same namespace group, and this will cover them too.

There's one final step: in order to get your autoloader to recognise the changes in composer.json you'll need to run the following (and again each time you make a change to your package.json):

composer install

This will trigger Composer to update the vendor/composer/autoload*.php files with that mappings to your new classes. You don't need to worry too much about those specific changes, as they are handled automatically by Composer. As such, you shouldn't really ever edit those files yourself, as changes could be overwritten the next time you run a Composer command which alters them.