Пространство имён PHP помещает классы, функции и константы под префикс, чтобы их имена не сталкивались с чужими. Его объявляют через namespace App\Models; первой инструкцией файла, а другие файлы обращаются к классу как \App\Models\User или импортируют его через use App\Models\User; и пишут просто User.
Внутри пространства имён User означает App\Models\User. User::class даёт полное имя строкой, ничего не создавая, что удобно для логирования и для автозагрузчиков.
Два пространства имён в одном файле
В реальном проекте в каждом файле одно пространство имён. Для самостоятельной демонстрации в одном файле может быть несколько пространств имён, если каждое обёрнуто в фигурные скобки. Код, который не относится ни к одному пространству имён, помещается в namespace { }:
Два класса с именем Order живут рядом, потому что их полные имена различаются. Именно эту проблему решают пространства имён, когда вы устанавливаете библиотеки: ваш Order, Order платёжной библиотеки и Order библиотеки для PDF больше не конфликтуют.
Импорт через use и псевдоним через as
Писать везде \Shop\Order громоздко. use в начале файла (или блока пространства имён) импортирует имя, чтобы можно было использовать короткую форму. Когда два импорта заканчиваются на одно и то же короткое имя, as даёт одному из них другое имя:
use лишь создаёт короткое имя до конца файла. Он не загружает файл и не выполняет код и работает одинаково, существует класс или ещё нет. Допускаются и групповые импорты: use Shop\{Order, Invoice};.
use function и use const
Функции и константы из пространства имён импортируются через use function и use const:
Глобальным классам нужен обратный слеш
Внутри пространства имён неквалифицированное имя класса разрешается относительно этого пространства, поэтому new DateTime() внутри namespace App; ищет App\DateTime. С функциями и константами иначе: если App\strlen не существует, PHP откатывается к глобальной strlen. Классы никогда не откатываются.
В catch (\Error $e) обратный слеш понадобился по той же причине: без него PHP искал бы App\Error, никогда не совпал бы с настоящей ошибкой, и скрипт остановился бы с неперехваченным Error. Исправьте это начальным обратным слешем, как выше, или через use DateTime; в начале файла. То же касается \Exception, \Throwable и любого другого встроенного класса; как их перехватывать, смотрите в try catch.
Автозагрузка и PSR-4
В проекте каждый класс лежит в своём файле, а путь к файлу следует пространству имён. PSR-4 это соглашение: префикс пространства имён сопоставляется базовой папке, а остаток имени становится путём. Автозагрузчик, зарегистрированный через spl_autoload_register(), загружает файл класса при первом использовании класса. Этот блок записывает на диск два файла классов и загружает их автоматически:
Каждый файл класса загружается один раз, в тот момент, когда класс впервые нужен. В реальных проектах эту функцию сами не пишут: её генерирует Composer по нескольким строкам в composer.json:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
После composer dump-autoload одна строка require __DIR__ . '/vendor/autoload.php'; в начале входного скрипта загружает любой класс App\... по требованию.
Правила пространств имён, которые приводят к ошибкам
namespaceдолжен быть первой инструкцией в файле. Перед ним могут стоять толькоdeclare(strict_types=1);и комментарии.- Импорты
useдействуют в пределах файла. Импорт класса вindex.phpне делает короткое имя рабочим внутри подключённого файла; каждому файлу нужны свои строкиuse. useставится на верхнем уровне файла или блока пространства имён. Внутри тела классаuseозначает другое: он подключает трейт.- Строки никогда не разрешаются:
$class = 'User'; new $class();ищет глобальныйUser. Храните полное имя, лучше всего черезUser::class.
Последнее правило стоит быстро проверить:
Часто задаваемые вопросы
Что такое пространство имён в PHP?
Префикс, который группирует связанные классы, интерфейсы, функции и константы, как папка для имён. namespace App\Models; в начале файла делает его класс User классом App\Models\User, поэтому он не может столкнуться с User из другой библиотеки.
Что делает use в PHP?
use App\Models\User; в начале файла позволяет писать в этом файле User вместо полного имени \App\Models\User. Он ничего не загружает и не подключает; загрузка файла класса это работа автозагрузчика. use ... as Alias; выбирает другое короткое имя.
Почему внутри пространства имён возникает Class not found?
Внутри namespace App; голое имя класса разрешается относительно пространства имён, поэтому new DateTime() ищет App\DateTime. Пишите new \DateTime() или добавьте use DateTime; в начало файла. Функции и константы автоматически откатываются к глобальному пространству имён, классы нет.
Что означает обратный слеш перед именем класса в PHP?
Начальный обратный слеш делает имя полностью квалифицированным, начиная от глобального пространства имён: \Exception это всегда встроенный Exception PHP, в каком бы пространстве имён ни был код. Без него имя разрешается относительно текущего пространства имён и импортов use.
Как пространства имён связаны с папками и PSR-4?
Сам PHP не привязывает пространства имён к папкам. Это делает соглашение PSR-4: префикс вроде App\ сопоставляется каталогу вроде src/, поэтому App\Models\User лежит в src/Models/User.php. Автозагрузчик Composer следует этому соглашению, поэтому обычно одно совпадает с другим.