Механізм автозавантаження класів в php

У даній статті я хочу розповісти як справи з автозавантаженням класів в PHP, а також про поширені підходах при реалізації автозавантаження.

У старому PHP коді звичайною практикою було використання функцій require, require_once, include, include_once для підвантаження файлів, що містять необхідні класи, наприклад:


таких require_once на початку файлів накопичувалось величезна кількість.

Чи погано це? Так.

Чому? Тому що:

- файли довантажувати в будь-якому випадку, навіть тоді коли в цьому не було ніякої необхідності
- постійно доводилося писати require / include і можна було запросто забути підключити якийсь файл
- в разі переміщення будь-якого файлу, доводилося міняти все що відносяться до нього require

Ті часи давно пройшли, тому що в PHP 5 з'явився механізм автозавантаження класів і функція __autoload (), яка викликається кожен раз, коли створюється об'єкт невідомого класу. Єдине що залишалося розробнику, так це реалізувати її, і більше не було необхідності писати require і т.д:


тому раніше ніде не був підключений файл, який містить клас User, то буде викликана функція __autoload (), якою буде передано ім'я класу як параметр $ class, і вона в свою чергу спробує підключити файл містить даний клас.

Ця функція дозволяє реєструвати будь-яку передану їй функцію як реалізацію механізму автозавантаження класів. Якщо ж викликати її без параметрів, то в якості реалізації автозавантаження буде виступати функція spl_autoload ()

Цей механізм має свою чергу, тому можна реєструвати більше одного функції для вирішення питань автозавантаження класів. Всі функції будуть викликані в порядку їх реєстрації. Також з версії 5.3 додана підтримка неймспейсов.

+ зручний механізм для автозавантаження класів з уже готовою реалізацією за замовчуванням

+ файли завантажуються лише тоді, коли це необхідно

+ немає необхідності писати купу require

Варіанти реалізації автозавантаження класів

Пропоную ознайомитися з поширеними підходами в реалізації Автозавантажувач і написати свої.

Ручна реєстрація класів для автозавантаження

Даний спосіб передбачає створення одного Автозавантажувач з можливістю реєстрації класів в ньому. Це може відбуватися в такий спосіб:

далі необхідно зареєструвати наш автозавантажувач:

Приступимо до його безпосереднього використання. Наприклад у нас є два класи User і Task, які знаходяться відповідно в /src/Model/User.php і /src/Model/Task.php, тоді щоб включити їх автозавантаження, нам необхідно зробити наступне:

потім в будь-якому місці, де нам потрібно буде зробити об'єкти цих класів, досить буде просто написати:

і спрацює метод autoload нашого Автозавантажувач.

Даний спосіб не ідеальний і має свої переваги:

+ замість постійних require досить один раз зареєструвати клас в Автозавантажувач

+ файли завантажуються тільки в міру їх необхідності

+ в разі зміни місця розташування файлу, досить змінити його шлях в одному місці

+ дозволяє додавати сторонні бібліотеки в проект, для цього потрібно лише додати їх класи в карту автолоадера

- необхідно реєструвати класи вручну

- не дозволяє по імені класу швидко визначити де він знаходиться

Імена класів як покажчики шляху до файлу

Даний спосіб автозавантаження класів використовується в шаблонизатор Twig, а також використовувався в Zend Framework'e першої версії. Суть його в тому, що саме ім'я класу вказує на папку, де знаходиться файл, який містить цей клас. Це легко зрозуміти на прикладі:

На основі цього прикладу легко написати функцію для автозавантаження класів, таких подібної угоди:

Вся його робота зводиться до одного дії - заміні підкреслень в назві класу на прямий слеш, формуючи таким чином шлях до файлу. В даному прикладі жорстко вказана коренева точка відліку початку шляху в файлової системі, поліпшення цього моменту я залишаю на совісті Новомосковсктеля.

Розглянемо переваги і недоліки даного Автозавантажувач.

+ немає необхідності вручну реєструвати класи

+ файли підключаються тільки в міру необхідності

+ по імені файлу легко визначити де він знаходиться

+ виключається можливість конфліктів в іменах класів, тому що не може бути два файли з однаковими іменами в файлової системі

- немає підтримки автозавантаження класів, не випливають з даною угодою при іменуванні класів, наприклад немає підтримки неймспейсов

- в разі серйозної реорганізації структури папок доведеться всюди переписувати імена класів

Автозавантаження класів, які використовують неймспейси

З моменту появи неймспейсов в PHP даний спосіб став одним з найпопулярніших. Суть в тому, що неймспейс необхідно пов'язати з певною папкою в файлової системі, а всі вкладені папки / файли будуть підхоплюватися автоматично. Нижче наведу приклад спрощеного Автозавантажувач, що підтримує роботу з неймспейсамі:

Далі розглянемо на прикладі використання цього Автозавантажувач:

В даному прикладі ми додали неймспейс Model, який вказує на папку src / Model. Далі коли ми створюємо об'єкт класу Alias ​​\ Robot, автозавантажувач отримує рядок Model \ Robot. По частині Model формується шлях src / Model, а по Robot - Robot.php, підсумковий шлях до файлу з класом Robot виходить src / Model / Robot.php.

Які ж плюси і мінуси такого підходу?

+ підтримка неймспейсов, які використовуються в багатьох сучасних бібліотеках

+ спрощена реєстрація неймспейсов в порівнянні з реєстрацією класів в першому Автозавантажувач

+ відсутність конфліктів в іменах класів, тому що кожен файл живе в своєму неймспейсе

- необхідно реєструвати неймспейси

P.s. Вихідний код Автозавантажувач зі статті, а також приклади їх використання можна побачити тут.