Що таке Автозавантаження; Як ви використовуєте spl_autoload, __autoload та spl_autoload_register?


203

Я вивчаю передові стандарти PHP і намагаюся впроваджувати нові і корисні методи. Раніше я використовував __autoloadлише для втечі, включаючи кілька файлів на кожній сторінці, але останнім часом я побачив підказку__autoload manual

spl_autoload_register () забезпечує більш гнучку альтернативу для автоматичного завантаження класів. З цієї причини використання __autoload () перешкоджає і може бути припинено або видалено в майбутньому.

але я дійсно не можу зрозуміти, як реалізувати spl_autoloadіspl_autoload_register

Відповіді:


334

spl_autoload_register() дозволяє реєструвати кілька функцій (або статичних методів з вашого власного класу автозавантаження), які PHP буде ставити в стек / чергу і викликати послідовно, коли оголошується "новий клас".

Так, наприклад:

spl_autoload_register('myAutoloader');

function myAutoloader($className)
{
    $path = '/path/to/class/';

    include $path.$className.'.php';
}

//-------------------------------------

$myClass = new MyClass();

У наведеному вище прикладі "MyClass" - це назва класу, до якого ви намагаєтеся інстанціювати, PHP передає це ім'я як рядок spl_autoload_register(), що дозволяє підібрати змінну та використовувати її для "включення" відповідного класу / файлу . Як результат, вам не потрібно спеціально включати цей клас через оператор включення / вимагати ...

Просто зателефонуйте до класу, який ви хочете створити, наприклад, у наведеному вище прикладі, і оскільки ви зареєстрували власну функцію (через spl_autoload_register()), яка визначить, де знаходиться ваш клас, PHP використовуватиме цю функцію.

Перевага використання spl_autoload_register()полягає в тому, що на відміну від __autoload()вас не потрібно реалізовувати функцію автозавантаження у кожному створеному файлі. spl_autoload_register()також дозволяє зареєструвати кілька функцій автоматичного завантаження, щоб прискорити автоматичне завантаження та зробити це ще простіше.

Приклад:

spl_autoload_register('MyAutoloader::ClassLoader');
spl_autoload_register('MyAutoloader::LibraryLoader');
spl_autoload_register('MyAutoloader::HelperLoader');
spl_autoload_register('MyAutoloader::DatabaseLoader');

class MyAutoloader
{
    public static function ClassLoader($className)
    {
         //your loading logic here
    }


    public static function LibraryLoader($className)
    {
         //your loading logic here
    }

Що стосується spl_autoload , в посібнику зазначено:

Ця функція призначена для використання як реалізація за замовчуванням для __autoload(). Якщо нічого іншого не вказано і spl_autoload_register()не викликається без будь-яких параметрів, ці функції будуть використовуватися для будь-якого подальшого виклику __autoload().

Більш практично, якщо всі ваші файли розміщені в одному каталозі, а ваша програма використовує не тільки файли .php, але й спеціальні файли конфігурації, наприклад, з розширеннями .inc, то однією стратегією ви могли б скористатись, щоб додати каталог, що містить усі Файли до PHP включають шлях (через set_include_path()).
А оскільки вам також потрібні ваші конфігураційні файли, ви б spl_autoload_extensions()перерахували розширення, які ви хочете шукати PHP

Приклад:

set_include_path(get_include_path().PATH_SEPARATOR.'path/to/my/directory/');
spl_autoload_extensions('.php, .inc');
spl_autoload_register();

Оскільки spl_autoload є реалізацією за замовчуванням __autoload()магічного методу, PHP зателефонує spl_autoload при спробі і інстанціювати новий клас.

Сподіваюся, це допомагає ...


35
Це може бути однією з найкращих відповідей за всю історію відповідей. Повага. У мене був один із таких "OMG! Це все має сенс!" моменти через тебе, мій добрий чоловік. Я думаю, що я можу просто створити фан-клуб.
Just Plain High

2
Щоб зробити це найкращою відповіддю на всі відповіді навіть у альтернативних всесвітах, будь ласка, додайте, що spl_autoload дуже, гм, "корисно" (?) Перетворює всі назви файлів у малі регістри (див. Коментар до @user нижче). Неможливо використовувати ваніль spl_autoload_register (), якщо вам подобається ваш CapitalLettersAndStuff.
Just Plain High

6
@Just Plain High У мене не виникає такої проблеми, і всі файли мого класу є вершковими. До речі, це чудова відповідь. Це допомогло мені взяти голову навколо простого поняття, яке я просто не міг зрозуміти, поки не прочитав цей пост! Мій 85 (і зростаючий) рядок включає файл, який включає всі файли мого класу зараз 7 рядків!
Кайл

2
Це справді хороша відповідь, але я пропускаю одне. Що таке фактична функціональність за замовчуванням? З класів, яких я знаю, він використовує простір імен як шлях, а ім'я класу - як ім'я файлу. Хоча я не можу зрозуміти, як це працює з функціями.
SiXoS

2
Чи не є однією з величезних переваг використання spl_autoload_register()__autoload()взагалі) того, що ледачі навантаження включають файли / класи? Це має на увазі відповідь, але прямо не зазначено. Для мене це важлива інформація, яка була б ідеальною для включення у вашу відповідь! :)
rinogo

13

Оскільки PHP 5.3, ви можете використовувати spl_autoload_register()з просторами імен, а це означає, що ви можете організувати свій проект та автоматично завантажувати ваші php-класи без будь-якої необхідності чи включення та без перевизначення __autoload()функції.

Щоб продемонструвати цю поведінку, просто створіть файл під назвою index.php:

<?php
spl_autoload_register();
var_dump(new Main\Application);

Потім створіть папку з назвою Main, розташовану поруч із файлом index.php. Нарешті, створює файл під назвою Application.php, розташований у Main, і вставляє в нього наступний код:

<?php namespace Main;
class Application{}

9
Примітка з мого співу з усім цим: spl_autoload () - і таким чином spl_autoload_register () - перетворює назви файлів у малі регістри (незважаючи на повідомлення про помилки, благання та шалене голосування). Це означає, що ви можете шукати "Головне \ Застосування", але spl_autoload шукає "головне \ додаток". Якщо ви любите верблюдів, як я, вам доведеться написати свою функцію. Тут є приємний приклад для початківців: github.com/ircmaxell/PHP-CryptLib/blob/…
Просто

1
Плюси: spl_autoload_register () - це найшвидший метод автоматичного завантаження мінусів: він буде працювати лише з малими файлами / класами, і просторами імен, які в цей день і вік просто значні для великого часу (немає можливості сказати йому використовувати CamelCase тощо). Але якщо ви можете жити зі структурою простору імен / classname.php, не дивіться далі.
stamster

1
spl_autoload_register()реалізація за замовчуванням не в змозі знайти успадковані класи. Таким чином, використовуючи за замовчуванням, малі файли та каталоги, що відображають шлях до простору імен, все працює нормально, якщо у мене немає класу, який розширює інший клас (батьківський). Потім PHP видає помилку, що не може знайти цей батьківський клас, навіть вони всі в одному каталозі / просторі імен! Що бентежить те, що знайдені буквально лише класи першого рівня, тому мені довелося поставити ще одне spl_autoload_register()правило з анонімною функцією відразу після першого класу, щоб вручну включити відсутні батьки / успадковані класи.
stamster

1

Ось як я використовую Autoload. У наведеному прикладі я хочу завантажувати класи з 3-х різних каталогів.

function namespaceAutoload($rawClass){

$class = str_replace('\\', DIRECTORY_SEPARATOR, $rawClass);

$possiblePaths[] = '..\sys\class\file.php';
$possiblePaths[] = '..\sys\class\lib\file.php';
$possiblePaths[] = '..\sys\class\class.file.inc.php';

foreach ($possiblePaths as $templatePath) {
    $path = str_replace(["\\", "file"], [DIRECTORY_SEPARATOR, $class], $templatePath);
    if (file_exists($path)) {
        require_once "$path";
        break;
    }
} spl_autoload_register("namespaceAutoload"); 

У наведеному прикладі PHP шукатиме простір імен \ class у цих трьох каталогах, використовуючи ці три різні формати імен файлів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.