PHP Autoloading Class Files

Summary: in this tutorial, you will learn how to organize your class files and load them automatically using PHP  spl_autoload_register() function.

It is good practice to keep each PHP class in a separate file. Also, the name of the class should be the same as the file name. For example, the Contact.php file should contain the Contact class.

Before using a class, you need to:

  • First, define the class in a file.
  • Second, load it using the require, require_once, include, or include_once statement.

Suppose that you have the following project directory structure:

.
├── index.php
└── models
    └── Contact.phpCode language: CSS (css)

The models directory has the Contact.php file that contains the following Contact class:

<?php

class Contact
{
	private $email;

	public function __construct(string $email)
	{
		$this->email = $email;
	}

	public function getEmail()
	{
		return $this->email;
	}
}
Code language: HTML, XML (xml)

From the index.php file, you can load the models/Contact.php file and use the Contact class as follows:

<?php

require_once 'models/Contact.php';
$contact = new Contact('[email protected]');
Code language: HTML, XML (xml)

This solution works fine if you have a small number of files. When the number of files grows, the require_once statement doesn’t scale well.

To resolve it, you can define a function that takes a class name as an argument and includes the file that contains the class definition. For example:

<?php

function load_model($class_name)
{
	$path_to_file = 'models/' . $class_name . '.php';

	if (file_exists($path_to_file)) {
		require $path_to_file;
	}
}Code language: HTML, XML (xml)

The load_class() function looks for the class file in the models directory and includes it if the file exists. And you can place the load_model() function in the functions.php file:

.
├── functions.php
├── index.php
└── models
    └── Contact.phpCode language: plaintext (plaintext)

To use the load_model() function in the index.php file, you can include the functions.php file and call the load_model() function:

<?php

require_once 'functions.php';

load_model('Person');

$person = new Person();Code language: HTML, XML (xml)

Autoloader with spl_autoload_register() function

PHP 5.1.2 introduced the spl_autoload_register() function that automatically loads a class file whenever you use a class that has not been loaded yet.

PHP 7.2.0 deprecated the __autoload() magic function and recommended to use the spl_autoload_register() function instead.

When you use a class that has not been loaded, PHP will automatically look for spl_autoload_register() function call.

The spl_autoload_register() function accepts a callback function and calls it when you attempt to create use a class that has not been loaded.

To use the spl_autoload_register() function, you can pass the load_model function to it as follows:

<?php

function load_model($class_name)
{
	$path_to_file = 'models/' . $class_name . '.php';

	if (file_exists($path_to_file)) {
		require $path_to_file;
	}
}


spl_autoload_register('load_model');
Code language: HTML, XML (xml)

And from the index.php file, you don’t need to call the load_model() function whenever you use a class in the models directory:

<?php

require 'functions.php';

$contact = new Contact('[email protected]');Code language: HTML, XML (xml)

Multiple autoload functions

The spl_autoload_register() function allows you to use multiple autoloading functions. The spl_autoload_register() function will create a queue of autoloading functions and runs through each of them in the order that they are defined.

For example:

<?php

spl_autoload_register('autoloader1');
spl_autoload_register('autoloader2');
spl_autoload_register('autoloader3');Code language: HTML, XML (xml)

In this example, PHP will run the autoloader1, autoload2, and autoloader3 sequentially to load the class files.

To demonstrate this, let’s create a new directory called services that stores service class files and create an Email.php file inside the services directory.

The following defines the Email class:

<?php

class Email
{
	public static function send($contact)
	{
		return 'Sending an email to ' . $contact->getEmail();
	}
}Code language: HTML, XML (xml)

The project directory now looks like this:

.
├── functions.php
├── index.php
├── models
│   └── Contact.php
└── services
    └── Email.phpCode language: plaintext (plaintext)

In the functions.php file, you can define a function that loads the classes from the services directory and pass the function name to the spl_autoload_register() function like this:

<?php

function load_model($class_name)
{
	$path_to_file = 'models/' . $class_name . '.php';

	if (file_exists($path_to_file)) {
		require $path_to_file;
	}
}

function load_service($service_name)
{
	$path_to_file = 'services/' . $service_name . '.php';

	if (file_exists($path_to_file)) {
		require $path_to_file;
	}
}

spl_autoload_register('load_model');
spl_autoload_register('load_service');Code language: HTML, XML (xml)

From the index.php, you can use the Contact and Email classes as follows:

<?php

require 'functions.php';

$contact = new Contact('[email protected]');

echo Email::send($contact);Code language: HTML, XML (xml)

Output:

Sending an email to [email protected]Code language: plaintext (plaintext)

Like classes, you can also load the interfaces and traits using same autoloading function.

Summary

  • An autoloading function loads a class, an interface, or a trait from a PHP file.
  • Use the spl_autoload_register() function to autoload the classes, interfaces, and traits.
Did you find this tutorial useful?