PSR-4, namespaces and Composer

Earlier this year I wrote a lovely article about our friend the autoloader and how you need never worry about the include, require or require_once functions again in PHP. Ah good times. However I want to touch on that subject, autoloading, again – mainly because, although better than before, it’s still not a perfect solution.

For me to do this I need to expand (briefly) on three things, namespaces, coding standards and Composer.

Namespaces essentially give context to classes and allows you to group things together. For instance each directory in a file system can be considered a namespace, and each namespace can be shared by files, can belong to a parent namespace or have child namespaces. In a namespace the name of something has to be unique.


"/home/user/Documents/"  // This is the Documents namespace

"/home/user/Downloads" // This is the Downloads namespace

"/home/user/Documents/test.php" // Therefore this can exist

"/home/user/Downloads/test.php" // As can this, neat eh? 

So how do we apply this in our code? And what has this got to do with autoloading?

Let’s say you want to write a package of code for an API to make requests, and parse responses through a set of helper methods. Ideally you will then want to either drop this code into your “big” projects code base, or allow others to do the same. Once dropped in it will sit alongside other packages, classes and functions.

So once completed, you do something along the lines of this….


<?php

    require "CustomPackage/Client.php";

    require "Twitter/Client.php";

    $custom = new Client($key);

    $twitter = new Client($username, $password);&nbsp; 

And a Fatal Error is thrown – informing you that you cannot redeclare classes.

Ah.

This is because they both exist in the Global namespace, it’s like trying to create test.txt twice in a directory – the system is telling you – “hold up a minute, that’s already there?”

This is where namespacing comes in, if we, in each of those files add the namespace keyword to the top of the file, and give it a relevant reference we can invoke it through its namespace.


<?php

    // In custom client we have ....

    namespace CustomClient;

    class Client{}

    // In the twitter client we have ...

    namespace TwitterClient;

    class Client{}

    // Back using these packages we can do....

    require "CustomPackage/Client.php";

    require "Twitter/Client.php";

    $custom = new CustomClient\Client($key);

    $twitter = new TwitterClient\Client($username, $password);

Hey presto. We’re away.

Coding standards are what keep developers sane. Essentially. Imagine you are jumping from project to project, or moving between employers, or departments, working on countless different code bases and existing developments. Little differences will be annoying such as the placement of braces ‘{}’ or the spacing round if statements. Some will be just plain odd, a tenery expression in an if block, and some will just be down right frustrating such as mixed casing on class-names and methods.

It’s enough to make you want to pack it all in and become a Tree Surgeon.

Coding standards provide a set of rules that should, to the highest degree, govern how a developer structures their code. It doesn’t deal too much with semantics such as how you name your variables, or syntax (it doesn’t iron out bugs). What is enforce grammatical rules, and styling.

Say you are reading a book.

The text is in a specific range of sizes. There are paragraphs and page numbers. Sentences start with capital letters. The book has a front cover, with a title, and the author, a blurb is included on the back and depending on the type of book and index / appendix is common.

Coding standards do for projects, what the above has done for reading. It promotes the readability of code and the digestion of what, how, and why it is behaving as it does, which lends itself to maintainability and you’ll thank yourself you have done this in exactly 8 months time when you have to make a change / fix a bug / or figure out what on earth you were thinking.

  • PHP has a set of standards that are formalised in the PHP Standard Recommendation or PSR’s.
  • PSR-0 is the original autoloading guide, however this has been superseded by PSR-4 (we’ll get to that in a minute).
  • PSR-1 is the basic coding standard and must be followed to comply with the other PSRs
  • PSR-2 is the coding style guide and builds on PSR-1
  • PSR-3 is the logger interface providing the rules for building logging classes and the methods / functionality they must implement
  • PSR-4 is the newest and shiniest iteration of the autoloading standard
  • PSR-7 is the HTTP message interface providing the rules on abstractions around HTTP messages and their composition

PSR-0, the deprecated technique, involved autoloading the code from a file structure that identically matched the namespace. So the autoloader you implemented in the callback function to the spl_autoload_register function had to search based on this principle.

So let’s say you have a Validation class with a namespace of Project_a\General the Validation class file (Validation.php) would have to be in src/Project_a/General/Validation.php where the entry point on to this project is in the src folder.

This has its benefits, obviously, however this can build a lot of redundant folders, especially when you are building your project to host on packagist and install with composer.

PSR-4 implicates that you must anchor a part of the namespace to a folder, such as src.

So say I am building an API client using mfmbarber/API – this can be anchored to src, so for instance Client.php can be in the namespace mfmbarber/API without having to have those two parent folders in the src directory. Pretty neat eh?

I can also have multiple projects in the src folder, such as API and Tools and map the mfmbarber/API and mfmbarber/Tools namespaces directly to these folders.

So how do we go about writing an autoloader that is PSR-4 compliant?

Well you could pick one up directly off of Git ?

Editors note : The next section assumes you are using composer 

But what if you are including live and dev dependancies packaged with composer – you don’t want to have to include another autoloader and have this conflict with composers autoloader – that’s a recipe for disaster!

Luckily Composer has you covered – you can make a small change to you composer.json file adding :

{
    "autoload": {
        "psr-4": {
            "mfmbarber\\API\\": "src"
        }
    }
}

In the above file we are telling composer, there is a namespace called mfmbarber\API, whenever a class is called in this namespace begin the searching from the src folder. If you have multiple namespaces in your project, then you can simply add their key values to this dictionary – like so…

{
    "autoload": {
        "psr-4": {
            "mfmbarber\\API\\": "src/API",
            "mfmbarber\\Tools\\": "src/Tools"
        }
    }
}

Finally simply call..


// Update the autoloader

// --optimize : Converts PSR-0/4 autoloading to classmap to get a faster autoloader. This is recommended especially for production, but can take a bit of time to run so it is currently not done by default.

$ composer dump-autoload --optimize

Now go and autoload, autoload, autoload

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s