Зачем указывать пространство имен при использовании автоматической загрузки psr-4 с помощью Composer?
Я немного смущен тем, как я должен использовать автоматическую загрузку psr-4 в Composer. Допустим, у меня такая структура папок:
/
|- Core/
| - Router.php
|- App/
| - Models
| User.php
|- composer.json
В основном, в корне проекта: composer.json; Основная папка, содержащая Маршрутизатор класс php; Приложение папка, содержащая Модели папка, содержащая Пользователя класс.
Класс маршрутизатора выглядит следующим образом:
<?php
namespace Core;
class Router {
}
И класс пользователей выглядит так это:
<?php
namespace App\Models;
class User {
}
Таким образом, я могу автоматически загружать эти классы с помощью автозагрузчика Composer psr-4, я могу сделать это в composer.json:
{
"autoload": {
"psr-4": {
"Core\\": "Core",
"App\\Models\\": "App/Models"
}
}
}
Таким образом, я могу использовать классы, не требуя их (после запуска composer dump-autoload
) следующим образом:
$router = new Core\Router();
$user = new App\Models\User();
Который работает без проблем.
Однако я также могу сделать это в composer.json:
{
"autoload": {
"psr-4": {
"": ""
}
}
}
, который, согласно документации, является резервным каталогом, в котором может находиться любое пространство имен относительно корневого. Таким образом, имея эту "пустую" запись в загрузчик composer, в котором, как я полагаю, написано ", начиная с корневого каталога, ищите класс в любом пространстве имен", я могу автоматически загружать любой из своих классов, если буду следовать правильной структуре именования папок/пространства имен.
Итак, мой вопрос в том, зачем мне делать первое, если второе работает и намного проще? Это связано с производительностью? Или есть другая причина?
3 answers
Почему бы тебе не делать это всегда "psr-4": {"": ""}
?
Причина 1: Это снижает производительность. В определении говорится, что для КАЖДОГО класса, которому требуется автоматическая загрузка, Composer должен заглянуть в корневой каталог. Эти классы входят не только в ваш пакет, но и во все остальные классы.
Композитор пытается немного оптимизировать эти усилия, запоминая бесплодные поиски, но это окупается только в том случае, если вы загружаете другой класс с тем же префиксом.
Причина 2: Суть PSR-4 заключается в том, что вам не обязательно сопоставлять весь путь к пространству имен с путем к каталогу. Предполагая, что у вас есть пакет, который имеет дело с очень специфической группой классов, таких как \Vendor\Template\Escaping\Output\*
, и ничего больше (наличие небольших пакетов облегчает их повторное использование без добавления слишком большого количества кода), вы можете иметь их в src/Vendor/Template/Escaping/Output/AnyClass.php
и определить
"psr-4": {
"\\Vendor\\Template\\Escaping\\Output\\": "src/Vendor/Template/Escaping/Output/"
}
Вы также можете поместить класс в src/AnyClass.php
и определить
"psr-4": {
"\\Vendor\\Template\\Escaping\\Output\\": "src/"
}
И это значительно сокращает путь к каталогу, незначительно повышая скорость (я думаю - хотя у меня нет цифр), но в основном улучшается разработка этой вещи за счет меньшего количества открываемых пустых папок.
Наличие пространства имен Core
и пространства имен App
в одном пакете вызывает у меня подозрения: почему для каждого из них нет одного пакета?
Обычно при использовании composer у вас есть только одна папка для вашего собственного проекта. Тогда вам нужно указать только одно пространство имен.
Подумайте, что вы изменили бы свою файловую структуру на
/
|- lib/
| - Core/
| - Router.php
| - App/
| - Models
| User.php
|- composer.json
И измените свой файл composer.json на
{
"autoload": {
"psr-4": {
"MyApp\\": "lib/"
}
}
}
Тогда у вас есть только одно указанное пространство имен, и вам не нужно добавлять какие-либо дополнительные пространства имен. Вы можете называть свои классы так:
$router = new \MyApp\Core\Router;
$user = new \MyApp\App\Models\User;
Или вот так:
namespace MyApp;
$router = new Core\Router;
$user = new App\Models\User;
PSR-4 - это стандарт, который преобразует пространства имен В физические каталоги.