1. Функция __autoload()
В php для автозагрузки классов можно использовать функцию
__autoload().
1.1 Файлы лежат в одной директории
Создадим файл
user.php:
<?php
class User {
public function __construct() {
echo 'Created User';
}
}
Допустим, что данный класс мы хотим использовать в файле
autoload_func.php:
<?php
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
function __autoload($class) {
require_once strtolower($class) . '.php';
}
new User();
При этом эти два файла расположены в одной директории.
При запуске скрипта
autoload_func.php класс User будет загружен автоматически. Нам не пришлось в файле
autoload_func.php писать вручную включение файла:
require_once 'user.php';. Также, если мы в этом файле обратимся к друкому классу, к примеру
new Company(), то благодаря
__autoload() интерпретатор php постарается включить файл
company.php, в котором должен располагаться класс
Company.
1.2 Файлы лежат во вложенных директориях
Теперь допустим, что у нас добавилась папка bank с файлом
account.php:
<?php
class Account {
public function __construct(){
echo 'Account created.';
}
}
Структура файлов выглядит так:
.
├── autoload_func.php
├── bank
│ └── account.php
└── user.php
Получается, что нужно php сообщить, что поиск файлов нужно осуществлять еще и в директории
bank:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
set_include_path('.');
set_include_path(get_include_path() . PATH_SEPARATOR . './bank' );
function __autoload($class) {
//Перечисляем пути поиска классов относительно
//текущего файла, где расположена эта ф-ция
$path_arr = array(
'.',
'bank'
);
foreach ($path_arr as $path) {
$file_path = $path.DIRECTORY_SEPARATOR.strtolower($class).'.php';
if (file_exists($file_path)) {
include_once $file_path;
}
}
}
new User();
new Account();
В этом случае при попытке создать класс
Account php приводит имя файла к нижнему регистру - account.php и проверяет его наличие сначала в текущей директории, затем в директории bank. Если файл существует, то он будет включен. Однако, это неверно, т.к. в папке bank может тоже быть файл с именем user.php, характеризующий пользователя банка. Из-за этого мы получим ошибку:
Fatal error: Cannot redeclare class User
Этой ошибки не возникнет, если в вашем проекте используются классы с уникальными названиями.
2. Функция spl_autoload_register()
Она предназначена для автозагрузки файлов используемых классов. Для примера 1.2. код с ее использованием выглядит так:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
$path_arr = array(
'.',
'bank'
);
foreach ($path_arr as $path) {
set_include_path(get_include_path(). PATH_SEPARATOR . $path);
}
spl_autoload_register(function($class) {
include_once strtolower($class) . '.php';
});
new User();
new Account();
И снова, если имена классов не будут уникальны, возникнет ошибка:
Fatal error: Cannot redeclare class ***.
Однако плюсом использования этой функции является отсутствие необходимости проверять наличие файла перед его загрузкой. Здесь мы просто посредством
set_include_path() добавляем к
include_path новые пути, а функция автозагрузки уже сама позаботится о включении нужных файлов.
Удобочитаемые имена загружаемых файлов
До сих пор мы обсуждали функции автозагрузки, которые поддерживали загрузку только таких файлов: bankuser.php, bankusercomment.php. Такие имена сложно читать, поэтому функцию автозагрузки нужно изменить, чтобы она стала работать с такими файлами: bank_user.php, bank_user_comment.php.
Чтобы это сделать, нужно придумать, как преобразовать строку имени класса "BankUserComment" в "bank_user_comment".
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
$path_arr = array(
'.',
'bank'
);
foreach ($path_arr as $path) {
set_include_path(get_include_path(). PATH_SEPARATOR . $path);
}
spl_autoload_register(function($class) {
include_once strtolower(
ltrim(
preg_replace('/[A-Z]/', '_$0', $class),
'_'
)
) . '.php';
});
new User();
new Account();
new BankUser();
В этом случае вы можете файл называть
bank_user_comment.php, а класс в нем так:
BankUserComment.
Разумеется, если вас устраивает, что файлы будут называться так: BankUserComment.php, то в функции автозагрузки нужно просто удалить преобразование имени к нижнему регистру -
strtolower().