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.php
Code language: CSS (css)
The models directory has the Contact.php file that contains the following Contact class:
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:
require_once 'models/Contact.php'; $contact = new Contact('john.doe@example.com');
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:
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.php
Code 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:
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:
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:
require 'functions.php'; $contact = new Contact('john.doe@example.com');
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.
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:
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.php
Code 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:
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:
require 'functions.php'; $contact = new Contact('john.doe@example.com'); echo Email::send($contact);
Code language: HTML, XML (xml)
Sending an email to john.doe@example.com
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.
Php autoload function files
Большинство разработчиков объектно-ориентированных приложений используют такое соглашение именования файлов, в котором каждый класс хранится в отдельно созданном для него файле. Одна из самых больших неприятностей — необходимость писать в начале каждого скрипта длинный список подгружаемых файлов (по одному для каждого класса).
Функция spl_autoload_register() позволяет зарегистрировать необходимое количество автозагрузчиков для автоматической загрузки классов и интерфейсов, если они в настоящее время не определены. Регистрируя автозагрузчики, PHP получает последний шанс для интерпретатора загрузить класс прежде, чем он закончит выполнение скрипта с ошибкой.
Любая конструкция, подобная классу может быть автоматически загружена таким же образом, включая классы, интерфейсы, трейты и перечисления.
До PHP 8.0.0 можно было использовать __autoload() для автозагрузки классов и интерфейсов. Однако это менее гибкая альтернатива spl_autoload_register() , функция __autoload() объявлена устаревшей в PHP 7.2.0 и удалена в PHP 8.0.0.
Замечание:
Функция spl_autoload_register() может быть вызвана несколько раз, чтобы зарегистрировать несколько автозагрузчиков. Выброс исключения из функции автозагрузки, однако, прервёт этот процесс и не позволит запускать дальнейшие функции автозагрузки. По этой причине выбрасывать исключения из функции автозагрузки настоятельно не рекомендуется.
Пример #1 Пример автоматической загрузки
В этом примере функция пытается загрузить классы MyClass1 и MyClass2 из файлов MyClass1.php и MyClass2.php соответственно.
spl_autoload_register (function ( $class_name ) include $class_name . ‘.php’ ;
>);
?php
$obj = new MyClass1 ();
$obj2 = new MyClass2 ();
?>
Пример #2 Ещё один пример автоматической загрузки
В этом примере представлена попытка загрузки интерфейса ITest .
spl_autoload_register (function ( $name ) var_dump ( $name );
>);
class Foo implements ITest >
Fatal error: Interface ‘ITest’ not found in .
*/
?>
Смотрите также
User Contributed Notes 6 notes
You should not have to use require_once inside the autoloader, as if the class is not found it wouldn’t be trying to look for it by using the autoloader.
Just use require(), which will be better on performance as well as it does not have to check if it is unique.
This is my autoloader for my PSR-4 clases. I prefer to use composer’s autoloader, but this works for legacy projects that can’t use composer.
/**
* Simple autoloader, so we don’t need Composer just for this.
*/
class Autoloader
public static function register ()
spl_autoload_register (function ( $class ) $file = str_replace ( ‘\\’ , DIRECTORY_SEPARATOR , $class ). ‘.php’ ;
if ( file_exists ( $file )) require $file ;
return true ;
>
return false ;
>);
>
>
Autoloader :: register ();
Autoloading plain functions is not supported by PHP at the time of writing. There is however a simple way to trick the autoloader to do this. The only thing that is needed is that the autoloader finds the searched class (or any other autoloadable piece of code) from the files it goes through and the whole file will be included to the runtime.
Let’s say you have a namespaced file for functions you wish to autoload. Simply adding a class of the same name to that file with a single constant property is enough to trigger the autoloader to seek for the file. Autoloading can then be triggered by accessing the constant property.
The constant could be replaced by any static property or method or by default constructor. However, I personally find a constant named ‘load’ elegant and informative. After all this is a workaround. Another thing to keep in mind is that this introduces an unnecessary class to the runtime. The benefit of this is that there is no need to manually include or require files containing functions by path which in turn makes code maintaining easier. Such behaviour makes it easier to alter the project structure since manual includes need not to be fixed. Only the autoloader needs to be able to locate the moved files which can be automated.
A code file containing functions.
/Some/Namespace/Functions.php
namespace Some \Namespace;
function b () >
?>
Triggering autoloading of the file containing functions.
main.php
\ Some \Namespace\ Functions :: load ;
It’s worth to mention, if your operating system is case-sensitive you need to name your file with same case as in source code eg. MyClass.php instead of myclass.php
Because static classes have no constructor I use this to initialize such classes.
The function init will (if available) be called when you first use the class.
The class must not be included before, otherwise the init-function wont be called as autoloading is not used.
function __autoload ( $class_name )
<
require_once( CLASSES_PATH . $class_name . ‘.cls.php’ );
if( method_exists ( $class_name , ‘init’ ))
call_user_func (array( $class_name , ‘init’ ));
return true ;
>
?>
I use it for example to establish the mysql-connection on demand.
It is also possilbe do add a destructor by adding this lines to the function:
if( method_exists ( $class_name , ‘destruct’ ))
register_shutdown_function (array( $class_name , ‘destruct’ ));
?>
Autoloading Classes with spl_autoload_register() or spl_autoload() is the best and most modern way to securely code for API integration.
It restricts the various attacks that can be faced by using a «polyfill» or framework that is subject to data injection. Low level attacks, polyfill and framework vulnerabilities are some exploitations limited in using the core functionalities of your host programming language.
Your loop-holes and target endpoints are vastly removed to the level of programming experience of the developer — in not exposing the threats espoused to your programming language and its security protocols.
Each event you transfer data from one program to the next reveals another threat and another attack endpoint. When you are production, it is at this point composer and other tools that gather requirements specific secure integration should limit its use, such as PCI-DSS, HIPAA, or GDPR.
The use of a framework or polyfill gives an attacker hints at what point a function will access memory to produce intended results. Visiting the late L1-Cache Terminal Fault — attacks that use machine language to access memory and read what actually is happening will have all the details of what process is taking place and when.
Not to mention, when a product is open-source, the code is editable and easily compiled. Using access to machine level integrations a simply 10 second loss of time to process could well as infer the entire application has experienced an overhaul.
To deter this, and ensure maximum security for piece of mind and money-wise. The embedded resources of a programming language should be utilized at maximal capacity to prevent an overhaul on multiple endpoints. Visiting a system in use is not deletable or easily moved, removed or altered.
- Классы и объекты
- Введение
- Основы
- Свойства
- Константы классов
- Автоматическая загрузка классов
- Конструкторы и деструкторы
- Область видимости
- Наследование
- Оператор разрешения области видимости (::)
- Ключевое слово static
- Абстрактные классы
- Интерфейсы объектов
- Трейты
- Анонимные классы
- Перегрузка
- Итераторы объектов
- Магические методы
- Ключевое слово final
- Клонирование объектов
- Сравнение объектов
- Позднее статическое связывание
- Объекты и ссылки
- Сериализация объектов
- Ковариантность и контравариантность
- Журнал изменений ООП