Auto Loading in PHP

Auto Loading in PHP

Auto loading in PHP is the means by which to load classes (and traits and things!) without needing to specifically require the class file. On smaller projects with one or two classes and a handful of files this might not seem like a big deal, but on larger project, particularly with classes from different vendors, and in frameworks like Laravel, auto loading becomes particularly important.

Our file structure

To follow this PHP autoloading tutorial you should be aware of our file structure. According to PSR4, we need to use namespaces for classes and as we’re trying to implement a basic PSR4 auto loader, we’ll do that.

Our file structure looks like this:

 

So, in our root directory we have an index.php file. We have a src directory and in src we have jsmcm/Logger/Log.php and manfred/Reader/Read.php.

Log.php and Read.php are classes and as you’ll see soon the jsmcm/Logger and manfred/Reader are namespaces which map directly to our file structure.

The old way of loading PHP classes – require

It used to be that if you wanted to load a class you needed to require the file before being able to declare instances of the class.

In the old days, to use the Log or Read classes we’d have to include the PHP class files before being able to use them. That would look something like this:

<?php

require __DIR__."/src/jsmcm/Logger/Log.php";
require __DIR__."/src/manfred/Reader/Read.php";

use \jsmcm\Logger\Log;
use \manfred\Reader\Read;

$oLog = new Log();
$oRead = new Read();

In this example we’ve now included the files we need and we use the fully qualified class names.

 

Our own custom auto loading example

The example above works. But lets assume we have many modules from many different vendors. We’d have to remember to include each file when we want to call a function in specific class. PSR4 style Auto loading our classes in PHP solves this problem by mapping fully qualified class names (that is, namespace’d class names) to directories and then having those files automatically loaded for us.

We know that our classes live in the src directory and that the classes themselves map their directory structures directly to their namespace and class names. Eg, the class jsmcm\Logger\Log() resides in a folder called jsmcm/Logger/Log.php.

Armed with this bit of PSR4 knowledge we can write our auto loader using PHP’s spl_autoload_register() function. This function takes a few parameters which you can read about on PHP’s own site. We’ll only use the first parameter which is a callback or in our case and anonymous function to implement the auto loader. spl_autoload_register passes the class name to our call back function.

So we now update our index.php file to look as follows:

<?php

use \jsmcm\Logger\Log;
use \manfred\Reader\Read;

spl_autoload_register(function($class){
   
    $baseDirectory = __DIR__.'/src/';
    
    $classPath = str_replace("\\", "/", $class).".php";
    
    if (file_exists($baseDirectory.$classPath)) {
        require $baseDirectory.$classPath;
    }
    
});

$oLog = new Log();
$oRead = new Read();

The anonymous function we use in spl_autoload_register() is given our base directory which in our case is src. We then build the class file path from the class name by converting the namespace separator \ to the file separator / and adding the .php extension.

Finally we use file_exists to see if the class file actually exists, and if it does we require it!

That’s pretty simple and works well. Provided we place all of our classes into the src directory and that the adhere to PSR4 this will work for us.

However, I can’t really recommend this approach. Its great to get an understanding of how auto loading might work and well worth playing with just as an educational exercise but in the real world we have the Composer Dependency Manager to help us with auto loading.

Composer dependency manager for our custom classes

In a previous blog post I spoke about using Composer Dependency Manager to load third party packages from Packagist. However, we can also use Composer to manage our own classes, or classes form third parties which are not packagist modules.

Composer uses a composer.json file to manage the packages in your application. To enable auto loading by Composer for our test project above we create a composer.json file with the following:

{
  "autoload": {
    "psr-4": {
      "jsmcm\\":"src/jsmcm",
      "manfred\\":"src/manfred"
    }
  }
}

This instructs composer that it needs to auto load classes for us using the PSR4 standard. For each specific vendor’s modules in our src directory we let composer know what the vendor’s vendor namespace name is and where that directory structure starts.

Once we’ve created our composer.json file we need to run:

composer dumpautoload -o 

on the command line. Composer will create a vendor directory with a bunch of files, but the one we’re interested in is the autoload.php file.

In our index.php file we can now remove our own spl_autoload_register() function and rather require composer’s autoloader with

require ‘./vendor/autoload.php’;

Our new index.php code now looks like this:

<?php

require "vendor/autoload.php";

use \jsmcm\Logger\Log;
use \manfred\Reader\Read;

$oLog = new Log();
$oRead = new Read();

While using composer for auto loading might add a little initial work in installing composer its well worth it. Composer is an extremely reliable and robust application. Furthermore, you’re not redeveloping the wheel with each application, right? You’re using packages from Packagist to slash your development time, right? If you are then you already use composer for those packages so it makes absolute sense to manage your own classes from your already existing composer.json file.

 

 

John McMurray is a freelance PHP developer. Experienced in PHP, Laravel and WordPress he can code anything you need.

Based in Plettenberg Bay, Western Cape I am available for PHP, Laravel or WordPress freelance jobs in Johannesburg, Pretoria, Cape Town, Port Elizabeth. I also often do remote PHP freelance work all over South Africa and the rest of the world.

Share

Leave a Reply

Your email address will not be published. Required fields are marked *