Auto-loading Classes in PHP

Autoloading is a PHP feature that allows our program to search and load files automatically given some set of predefined rules. Each time we reference a class that PHP does not know about, it will ask the autoloader. If the autoloader can figure out which file that class is in, it will load it, and the execution of the program will
continue as normal. If it does not, PHP will stop the execution.

So, what is the autoloader? It is no more than a PHP function that gets a class name as a parameter, and it is expected to load a file. There are two ways of implementing an autoloader: either by using the __autoload function or the spl_autoload_ register one.


Using the __autoload function

Defining a function named __autoload tells PHP that the function is the autoloader that it must use. We could implement an easy solution:

function __autoload($classname) {
$lastSlash = strpos($classname, '\\') + 1;
$classname = substr($classname, $lastSlash);
$directory = str_replace('\\', '/', $classname);
$filename = __DIR__ . '/' . $directory . '.php';
require_once($filename);
}

Our intention is to keep all PHP files in src, that is, the source. Inside this directory, the directory tree will emulate the namespace tree of the classes excluding the first section BookStore, which is useful as a namespace but not necessary as a directory. That means that our Book class, with full class name BookStore\Domain\Book, will
be in src/Domain/Book.php(Example for understanding).

In order to achieve that, our __autoload function tries to find the first occurrence of the backslash \ with strpos, and then extracts from that position until the end with substr. This, in practice, just removes the first section of the namespace, BookStore.

After that, we replace all \ by / so that the filesystem can understand the path. Finally, we concatenate the current directory, the class name as a directory, and the .php extension.

Before trying that, remember to create the src/Domain directory and move the two classes inside it. Also, to make sure that we are testing the autoloader, save the following as your init.php, and go to http://localhost:8000/init.php:

<?php
use Bookstore\Domain\Book;
use Bookstore\Domain\Customer;
function __autoload($classname) {
 $lastSlash = strpos($classname, '\\') + 1;
 $classname = substr($classname, $lastSlash);
 $directory = str_replace('\\', '/', $classname);
 $filename = __DIR__ . '/src/' . $directory . '.php'
 require_once($filename);
}
$book1 = new Book("1984", "George Orwell", 9785267006323, 12);
$customer1 = new Customer(5, 'John', 'Doe', 'johndoe@mail.com');

The browser does not complain now, and there is no explicit require_once. Also remember that the __autoload function has to be defined only once, not in each file.

So from now on, when we want to use our classes, as soon as the class is in a namespace and file that follows the convention, we only need to define the use statement. This method is way cleaner and easy.


Using the spl_autoload_register function

The __autoload solution looks pretty good.We cannot define two functions with the same name, we need a way to tell PHP to keep a list of possible implementations of the autoloader, so it can try all of them until one works.

That is the job of spl_autoload_register. We define your autoloader function with a valid name, and then invoke the function spl_autoload_register, sending the name of our autoloader as an argument.

We can call this function as many times as the different autoloaders we have in your code. In fact, even if we have only one autoloader, using this system is still a better option than the __autoload one, as we make it easier for someone else who has to add a new autoloader later:

function autoloader($classname) {
 $lastSlash = strpos($classname, '\\') + 1;
 $classname = substr($classname, $lastSlash);
 $directory = str_replace('\\', '/', $classname);
 $filename = __DIR__ . '/' . $directory . '.php';
 require_once($filename);
}
spl_autoload_register('autoloader');

This is all about the Auto-loading Classes in PHP.

Leave a Comment

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