Механізм автозавантаження класів в 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. Вихідний код Автозавантажувач зі статті, а також приклади їх використання можна побачити тут.