Неймспейсы и автозагрузка в php

Об автозагрузке в PHP

При написании приложений, код размещают в отдельных файлах. Чтобы код одного файла использовать в другом, его необходимо подключить через функцию require_once или include_once

Времена до автозагрузки

До PHP 5.0 (2005 г.) использовались подключение файлов через многократные вызовы фукнций require_once

Магический метод __autoload

Данный метод объявлен УСТАРЕВШИМ начиная с PHP 7.2.0 и его использование крайне не рекомендовано.

Уже при этом подходе здравый смысл подсказывал, что в одном файле должен находится один класс, а название класса должно совпадать с названием файла.

В PHP 5.1.2 (2006 г.) эти проблемы решили через фукнции автозагрузчики.

Автозагрузка через spl_autoload_register

PHP позволяет зарегистрировать любое число функций-автозагрузчиков с помощью функции spl_autoload_register. В случае обращения к несуществующему в данный момент классу, PHP будет вызывать по очереди все зарегистрированные автозагрузчики, передавая им имя класса. Если автозагрузчик знает, где лежит этот класс, он должен подключить файл с ним, PHP увидит, что класс появился, и продолжит выполнение программы. Иначе PHP вызовет следующий автозагрузчик. Если ни один автозагрузчик не подключит файл с классом, то будет выведена ошибка об обращении к несуществующему классу.

Если подключается сторонняя библиотека, то она может зарегистрировать свой автозагрузчик для загрузки своих классов. Таким образом, каждая библиотека может устанавливать свои правила для поиска файлов со своими классами.

Есть fallback для __autoload :

Автозагрузка через composer и PSR-4

Развитием идеи в одном файле один класс стал стандарт PSR-0 (англ.) (устаревший) и его развитие PSR-4 (англ.). PSR-4 говорит как надо называть классы, чтобы по полному имени класса узнать путь к файлу (чтобы потом его подключил автозагрузчик).

Пример пакета foo-bar по PSR-4

На сегодняшний день большинство PHP разработчиков пользуются загручиком из менеджера зависимостей Сomposer. Composer не является только лишь генератором автозагрузчика. Задачи, которые он выполняет намного шире.

Генерация и использование автозагрузчика из composer

Пример раздела в файле composer.json говорящий, что классы из namespace’a Foo находятся в папке src, а классы из App\Plugins надо искать в plugins/.

Соответственно классы будут искаться так:

После добавления информации в composer.json, надо выполнить команду гененрирации загрузчика

или при установленном composer

Команда сгенерирует файлы автозагрузчика и положит их в папку vendor. После этого надо подключить автозагрузчик в свои файлы и наслаждаться программированием.

Таким образом, следование PSR-4 и использование composer позволяет не писать свой автозагрузчик.

Похожие записи

Отладка PHP в Visual Studio Code и OpenServer

Источник

PHP Namespace

Пространство имён (англ. namespace) — некоторое множество, под которым подразумевается модель, абстрактное хранилище или окружение, созданное для логической группировки уникальных идентификаторов (то есть имён). Идентификатор, определенный в пространстве имён, ассоциируется с этим пространством. Один и тот же идентификатор может быть независимо определён в нескольких пространствах. Таким образом, значение, связанное с идентификатором, определённым в одном пространстве имён, может иметь (или не иметь) такое же (а скорее, другое) значение, как и такой же идентификатор, определённый в другом пространстве. Языки с поддержкой пространств имён определяют правила, указывающие, к какому пространству имён принадлежит идентификатор (то есть его определение).wiki

Все ясно? На самом деле все просто. До версии 5.3 в php существовало всего два пространства — глобальное(в котором выполнялся ваш основной код) и локальное(в котором определялись переменные функций).
Неймспейсы и автозагрузка в php. Смотреть фото Неймспейсы и автозагрузка в php. Смотреть картинку Неймспейсы и автозагрузка в php. Картинка про Неймспейсы и автозагрузка в php. Фото Неймспейсы и автозагрузка в php
С версии 5.3 все изменилось. Теперь можно определить свое пространство имен, в котором будут существовать ваши классы методы и т.д.
Неймспейсы и автозагрузка в php. Смотреть фото Неймспейсы и автозагрузка в php. Смотреть картинку Неймспейсы и автозагрузка в php. Картинка про Неймспейсы и автозагрузка в php. Фото Неймспейсы и автозагрузка в php
Надеюсь стало немного понятнее.

Я специально обозвал классы одинаково. Так они определены в разных пространствах, то это два разных класса, несмотря на одинаковые имена. Основной скрипт,-по прежнему, функционирует в глобальном пространстве, здесь ничего не изменилось и в нем, по-прежнему, можно определять классы и функции. Так для чего же тогда нужны пространства? Прежде всего, для уверенности в том, что когда вы подключаете файл, с каким-нибудь фреймворком или библиотекой, ваши классы не переопределят классы фреймворка или наоборот.

Для того, чтобы использовать классы определенные в своем пространстве имен, необходимо в нужном месте(я как правило предпочитаю делать это в начале файла) импортировать определенное вами пространство в глобальное для этого используется ключевое слово

Внимание: по каким-то своим основаниям php не допускает использование ключевого слова use в блоках условий и циклах

возьмем пример с картинок и воплотим его в коде:

Внимание: ключевое слово namespase должно быть расположено в самом начале файла сразу после

Источник

Неймспейсы и автозагрузка в PHP

В этом уроке мы коснемся архитектуры приложений. Если быть точнее – мы научимся тому, как в современном программировании на PHP принято хранить классы в отдельных файлах, и о том, как избегать при этом бесконечных строчек с include и require для подключения этих файлов.

На самом деле, в PHP всё довольно просто с правилами по реализации большинства частей приложения. Для этого есть уже придуманные умными людьми стандарты – PSR (PHP Standards Recommendations). В них описано, как нужно писать ту или иную составляющую вашей программы.

В этом уроке мы затронем стандарт PSR-4. В нём говорится о том, что каждый класс должен храниться в отдельном файле и находиться в пространстве имён. Давайте обо всём по порядку.

Пусть у нас есть классы User и Article. Нам нужно сохранить их в разных файлах. Для этого давайте создадим рядом с папкой www папку src, а внутри неё папку MyProject. Внутри папки MyProject создадим папку Models, а в ней создадим ещё 2 папки – Articles и Users. И уже в этих папках создадим файлы Article.php и User.php. Должно получиться следующее:

Неймспейсы и автозагрузка в php. Смотреть фото Неймспейсы и автозагрузка в php. Смотреть картинку Неймспейсы и автозагрузка в php. Картинка про Неймспейсы и автозагрузка в php. Фото Неймспейсы и автозагрузка в php

Давайте теперь опишем в этих двух файлах наши классы.
src/MyProject/Models/Articles/Article.php

Первую часть сделали – теперь у нас каждый класс лежит в отдельном файле. Давайте теперь перейдём в наш index.php, лежащий в директории www и запишем в него логику для работы с этими классами.

Давайте теперь попробуем запустить этот скрипт в браузере.
Разумеется, мы получим ошибку.

Неймспейсы и автозагрузка в php. Смотреть фото Неймспейсы и автозагрузка в php. Смотреть картинку Неймспейсы и автозагрузка в php. Картинка про Неймспейсы и автозагрузка в php. Фото Неймспейсы и автозагрузка в php

Нашему скрипту не удалось найти класс User. Давайте подключим файлы с нужными нам классами в начале index.php

Если мы сейчас запустим этот скрипт, то всё у нас прекрасно отработает и мы увидим результат var_dump().

Неймспейсы и автозагрузка в php. Смотреть фото Неймспейсы и автозагрузка в php. Смотреть картинку Неймспейсы и автозагрузка в php. Картинка про Неймспейсы и автозагрузка в php. Фото Неймспейсы и автозагрузка в php

Итак, с первым пунктом про хранение классов в отдельных файлах мы разобрались.

Теперь вернёмся к пространствам имён – неймспейсам. Тут всё довольно просто – класс можно поместить в отдельное именованное пространство и в дальнейшем использовать его по этому полному имени. Для того чтобы указать это пространство для конкретного класса используется слово namespace, за которым следует само имя. Указывается оно в файле с классом, перед определением класса. На примере класса User это будет выглядеть следующим образом:
src/MyProject/Models/Users/User.php

Теперь мы можем говорить, что класс User находится в неймспейсе MyProject\Models\Users.

Давайте проделаем аналогичные действия с классом Article.
src/MyProject/Models/Articles/Article.php

Теперь, чтобы в файле index.php работать с данными классами, мы должны указать полное имя класса – это имя класса с указанием его неймспейса. Делается это следующим образом.
www/index.php

Если мы сейчас запустим скрипт, то снова столкнёмся с ошибкой.

Неймспейсы и автозагрузка в php. Смотреть фото Неймспейсы и автозагрузка в php. Смотреть картинку Неймспейсы и автозагрузка в php. Картинка про Неймспейсы и автозагрузка в php. Фото Неймспейсы и автозагрузка в php

Но на этот раз, она уже другая. А именно – третий аргумент, переданный в конструктор класса Article должен быть объектом класса MyProject\Models\Articles\User, а передан объект класса MyProject\Models\Users\User. Заметили ошибку? Неймспейс не тот. Дело в том, что если в файле с классом указан неймспейс, то все классы, которые указываются в данном файле будут искаться в том же неймспейсе. Так как у нас класс User находится в другом неймспейсе, то мы должны явно это указать. Вот так:
src/MyProject/Models/Articles/Article.php

Либо же указать в начале файла о каком классе идёт речь, когда мы используем в коде только слово User. Делается это с помощью слова use после указания текущего неймспейса, но перед описанием класса.

Теперь, когда мы будем использовать класс User, то автоматически будет использоваться класс из неймспейса MyProject\Models\Users\User.

Давайте снова запустим скрипт, и убедимся, что всё у нас теперь работает.

Получили работающий скрипт. Ура! Вот в принципе и всё, что вам нужно знать о неймспейсах. В наших будущих программах мы всегда будем создавать классы внутри неймспейсов.

Автозагрузка

Однако, давайте снова посмотрим на наш файл index.php. представьте, что у нас теперь большой проект и в нём больше 100 классов. Нам придётся сто раз писать require с указанием каждого файла. Утомительно, да? Однако, можно автоматизировать этот процесс, написав функцию автозагрузки классов. Она будет вызываться каждый раз, когда впервые будет встречаться новый класс.

Итак, давайте сделаем эту функцию автозагрузки. Давайте я сначала приведу пример кода, а затем объясню, как это работает. Наш файл index.php принимает следующий вид:

А теперь по порядку о том, что же происходит.

Всё! Теперь все классы будут подгружаться автоматически. Давайте запустим скрипт и убедимся, что всё работает.

Снова запустим скрипт и посмотрим на вывод.

Мы видим, что в эту функцию попал сначала класс MyProject\Models\Users\User, а затем MyProject\Models\Articles\Article. И для этих классов мы сделали require нужных файлов и они успешно подгрузились.

На этом давайте var_dump уберём.

В функцию spl_autoload_register можно и вовсе передать не имя функции, а прямо саму функцию – не будем сейчас на этом останавливаться более детально. Просто знайте, что так можно:

В таком случае, функция называется анонимной – у неё нет имени. Она просто передаётся в качестве аргумента и имя ей не нужно.

Запустите код ещё раз, и убедитесь, что всё работает как нужно.
Вот такими вот нехитрыми действиями мы сделали автозагрузку классов. PHP – прекрасный язык, не правда ли?

Начиная с текущего урока я решил выкладывать итоговые результаты уроков на github, чтобы вам в случае чего можно было свериться с кодом, который должен был получиться в конце урока. Вот ссылка на результат этого урока.

Источник

Предисловие переводчика

Данная статья является вольным переводом-пересказом поста The End of Autoloading
. Оригинальная статья не первой свежести, поэтому код приведенный в примерах может быть не актуален. В теме, которую затрагивает статья, самое главное — общий взгляд, а не конкретные примеры.

Предисловие

Автозагрузка в PHP отлично экономит время. Это позволяет писать скрипты не задумываясь о путях к библиотекам, которые вы используете. Но с приходом неймспейсов и под влиянием Java-стиля современных фреймворков ситуация изменилась. В ближайшем будущем автозагрузка будет повсеместно, но без единой выгоды старого ее стиля.

До автозагрузки. Пути к файлам.

До появления автозагрузки, в каждом скрипте необходимо было указывать пути к используемым библиотекам. Исходный код выглядел так:

Зависимости явно прописывались в начале каждого скрипта. В этом примере зависимость очевидна, даже если вызов PEAR_DependencyDB находится на 328 строке.

Приход SPL-автозагрузки.

Позже появилась функция spl_autoload_register(), позволившая убрать вызовы require/require_once. Замечательным было то, что теперь появилась возможность использовать классы без необходимости знания где они расположены. Например:

Смотрите, здесь нет ни единого вызова require/require_once, при том, что этот класс зависим от sfActions, PostPeer, и Criteria классов. Разработчики смогли заниматься бизнес-логикой, не тратя время на поиск путей зависимостей. Это было действительно удобно.

Реализации автозагрузки.

Реализации автозагрузки варьируются. Некоторые библиотеки используют список всех классов, которые нужно подключить. Например:

Эта техника позволила скрыть пути к классам, но заставила разработчика библиотеки обновлять “карту” автозагрузки, каждый раз, при добавлении нового класса. Другая техника использует проход по структуре папок проекта в поиске нужного класса. Такой подход позволил подменять классы фреймворка своими, т.к. проход по папкам происходил в определенном порядке: пользовательские папки, проекта, плагинов и фреймворка. Таким образом разработчик мог создать класс ClassName, который подменит ClassName предоставленный плагином, т.к. загрузится раньше.

Автозагрузка с неймспейсами

Приход неймспейсов изменил техники автозагрузки. Авторы фреймвроков объединились, что бы унифицировать техники автозагрузки, для возможности технического взаимодействия между различными библиотеками. Было решено, что явное лучше неявного и полное имя класса будет относительным путем к файлу.

Были выработаны принципы именования и файловой структуры, а также реализация класса SplClassLoader. Этот подход сейчас используется практически во всех современных фреймворках. Пример кода:

Здесь все также нет require благодаря автозагрузке. Автозагрузчик ищет Symfony\Framework\WebBundle\Controller класс в файле Symfony/Framework/WebBundle/Controller.php.
Все хорошо, все довольны. Зависимости явные и подмена класса происходит легко:

Конец все удобствам.

Использование use в предыдущем примере вам ничего не напоминает? Это ведь очень похоже на старый добрый require/require_once, не так ли?

Привнесенная неймспейсами многословность в первую очередь снижает легкость использования автозагрузки. Но проблема не только в том, что нужно писать больше кода, в этом вам может помочь IDE с автодополнением, а в том, что вам нужно знать полные имена нужных вам классов. Вы должны очень хорошо знать классы фреймворка, чтобы использовать их. Это шаг назад по сравнению с автозагрузкой “первого поколения”, где было достаточно знать имя класса.

Другого пути нет.

Правда было бы замечательно, использовать современные библиотеки без знания их файловой структуры? Что если бы вы могли написать контроллер так:

Умный автозагрузчик перехватил бы вызов класса Controller, загрузил бы файл Symfony/Framework/WebBundle/Controller.php и динамически создал алиас с Symfony\Framework\WebBundle\Controller на Controller. К сожалению в PHP use создает алиас во время компиляции, поэтому такой ход не сработает. Конечно есть возможность сделать подобное используя eval, но это, наверное, даже хуже, чем подключать файлы вручную. Также создание таких алиасов при работе с фреймворком не возможно по причине конфликта с ленивой загрузкой и конфликта имен классов, например:
Symfony\Framework\WebBundle\Command
и
Symfony\Components\Console\Command\Command
Пока авторы фреймворков не изменят свой взгляд на автозагрузку, будущее PHP мне видится многословным.

Решение проблемы.

Лично я, думаю, что многословность сильно замедляет разработку. Например возьмем микрофреймворки – они дают возможность обработать запрос быстро, при минимуме MVC-разделения. Сравним код примерного приложения написанного с использованием Slim (автозагрузка без неймспейсов) и Silex (автозагрузка с неймспейсами):

Во втором примере, автозагрузка делает все только сложнее.

Разработчики современных фреймворков объясняют, что многословность – это цена, которую мы платим за качество кода. Я не уверен, что хочу платить эту цену. Я не хочу видеть как PHP превращается в Java, где код превосходен с точки зрения Computer Science, но очень затратен в написании. Это побуждает желание к использованию других языков, где вопрос автозагрузки с неймспейсами не стоит и при этом, быстрая разработка возможна.

Возьмем например Ruby. Существует такой фреймворк как Sinatra, используя который HelloWorld-приложение становится очень лаконичным:

Ой, смотрите, здесь же используется require! И при этом, все пишется очень быстро и легко в использовании.

Источник

Как использовать пространства имён в PHP, Часть 3: Ключевые слова и автозагрузка

Константа __NAMESPACE__

__NAMESPACE__ это строка PHP, которая всегда возвращает текущее имя пространства имён. В глобальном пространстве она будет всегда пустой строкой.

Её значение имеет очевидную выгоду во время отладки. Её также можно использовать чтобы динамически генерировать полные квалифицированные имена классов, например:

Ключевое слово namespace

Ключевое слово namespace может использоваться для того чтобы явно указать источник позиции (дать на него ссылку) в пределах текущего пространства имён или подпространства имён. Эквивалент namespace — ключевое слово self для классов:

Автозагрузка классов пространств имен

Одна из наилучших возможностей экономящих время в PHP 5 это автозагрузка. В глобальном (не отнесенном к какому-либо пространству имен) PHP коде, стандартная функция автозагрузки может быть записана следующим образом:

В качестве альтернативы, файловая иерархия Ваших классов может быть организована таким же образом как и структура Ваших пространств имен. Например, файл MyClass.php может быть создан в папке /classes/App/Lib1 :

/classes/App/Lib1/MyClass.php:

Файл, находящийся в корневой директории может его использовать с помощью следующего кода:

myapp.php:
Пояснение:

Я надеюсь что Вам пригодится эта серия статей о пространствах имён PHP. Будете ли Вы использовать пространства имён в своем PHP коде?

Читайте также:

Примечания:

Ключевое словов namespace может быть использован для четкой связи между текущим пространством имени и подпространствами на подобии self в классах

Ключевое слово namespace может использоваться для того чтобы явно указать источник позиции (дать на него ссылку) в пределах текущего пространства имён или подпространства имён. Эквивалент namespace — ключевое слово self для классов

B/ Замечания, поправки, указания на неточности и проч. — приветствуются!

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *