Understanding spl_autoload_register and PHP’s autoloading mechanism
Note: All the code in this article can be found in this GitHub repo.
The trouble with require
Usually, when we want to use a class or function that’s defined in another file, we have to require
or include
them:
<?php
require 'lib/classes/GreeterService.php'; # We must explicitly specify the paths
require 'lib/classes/DateService.php';
$greeter = new GreeterService();
$greeter->greet('Jimmy');
$date = new DateService();
$date->printDate();
But manually requiring files like this becomes tedious and unmaintainable when our project grows. Suppose you decide to move the GreeterService.php
file to some other location, you’d then have to update all the require
statements.
spl_autoload_register
to the rescue
Fortunately, PHP gives us the spl_autoload_register
function to make life easier. spl_autoload_register
has the following signature:
spl_autoload_register(
callable $autoload_function = ?,
bool $throw = true,
bool $prepend = false
): bool
For now, let’s focus on the first argument – the autoload_function
. Using spl_autoload_register
, we can replace the previous code with the require
statements to something like this:
<?php
spl_autoload_register('classLoader');
function classLoader(string $className)
{
$filePath = __DIR__ . "/lib/classes/$className.php";
if (is_readable($filePath)) {
require $filePath;
}
}
$greeter = new GreeterService();
$greeter->greet('Jimmy');
$date = new DateService();
$date->printDate();
How spl_autoload_register
works under the hood
Every time you reference a class (e.g., new Foo()
), PHP looks at a queue of autoloaders to see if any of them can resolve the given class. spl_autoload_register
allows you to add your own autoloader to this queue. This means you can tell PHP how to automatically find classes in certain directories.
Tidying up the custom autoloader
To clean up our code, it’s a good idea to move the autoloading logic into a dedicated autoload.php
file:
<?php
class Autoloader
{
public static function ClassLoader(string $className)
{
$filePath = __DIR__ . "/lib/classes/$className.php";
if (is_readable($filePath)) {
require $filePath;
}
}
}
spl_autoload_register('Autoloader::ClassLoader');
# You can define multiple autoloaders:
# spl_autoload_register('Autoloader::ServiceLoader');
# spl_autoload_register('Autoloader::ControllerLoader');
# etc...
Then we can require
this autoload file just once at the start of our application:
<?php
require_once __DIR__ . '/autoload.php';
$greeter = new GreeterService();
$greeter->greet('Jimmy');
$date = new DateService();
$date->printDate();
That looks so much cleaner. Now if we want to add new classes under our existing lib/classes
directory, our autoload.php
file automatically registers these classes. We don’t have to require
them when we use them.
Wrapping up
Most PHP developers nowadays use Composer and PSR-4 autoloading so that they don’t have to bother defining their own autoloaders as we’ve done in this article. Composer takes care of generating an autoload.php
file for you so that you typically just need to do add a require vendor/autoload.php
line at the start of your application ( see example) .
But it’s good to understand how things work under the hood and hopefully, this article has helped you understand PHP’s autoloading mechanism a little better.
Thanks for your comment 🙏. Once it's approved, it will appear here.
Leave a comment