Статьи

Битва автозагрузчиков: PSR-0 против PSR-4

Если вы прошли начальный этап обучения PHP, вы слышали о PSR-0 — стандарте автозагрузки, который определяет способы автоматического включения классов PHP в ваш код без необходимости использования таких операторов, как requireinclude

PSR-0

PSR-0 просматривает пространство имен класса и определяет его местоположение на жестком диске по этой информации. Например, класс \Zend\Mail\Message/path/to/project/lib/vendor/Zend/Mail/Message.php

PSR-0 также поддерживает подчеркивания в именах классов в качестве альтернативы, чтобы упростить переход с 5.2 и более ранних версий. Zend_Mail_Message/path/to/project/lib/vendor/Zend/Mail/Message.php

Композитор

Когда появился Composer и взял штурмом мир управления пакетами PHP, все изменилось. Из-за некоторых из его правил папки часто дублируются и становятся слишком глубокими при просмотре установок класса PSR-0 через Composer. Например, некоторые структуры папок выглядят так:

 vendor/
    vendor_name/
        package_name/
            src/
                Vendor_Name/
                    Package_Name/
                        ClassName.php       # Vendor_Name\Package_Name\ClassName
            tests/
                Vendor_Name/
                    Package_Name/
                        ClassNameTest.php   # Vendor_Name\Package_Name\ClassNameTest

В лучшем случае это хаотично, потому что:

Каталоги «src» и «tests» должны включать имена каталогов vendor и package. Это артефакт соответствия PSR-0.

Поэтому некоторые высококвалифицированные разработчики PHP собрались вместе и предложили новый стандарт: PSR-4 .

PSR-4

PSR-4 стремится дополнять и работать вместе с PSR-0 там, где это необходимо, а не полностью заменять его. Может, но не обязательно. Основная цель PSR-4 состоит в том, чтобы полностью удалить остатки PSR-0 и дней до 5.3 и обеспечить более краткую структуру папок. С PSR-4 вышеприведенное дерево папок будет выглядеть так:

 vendor/
    vendor_name/
        package_name/
            src/
                ClassName.php       # Vendor_Name\Package_Name\ClassName
            tests/
                ClassNameTest.php   # Vendor_Name\Package_Name\ClassNameTest

Обновление PSR-0 не было вариантом

потому что PSR-0 не допускает промежуточный путь между любыми частями имени класса

Это очень важно — это означает, что реализация PSR-4, позволяющая создавать намного более чистые пакеты, будет гораздо сложнее реализовать. Мы называем PSR-4 пакетно-ориентированной автозагрузкой, потому что она способствует чистоте пакета перед простотой.

Выбранный подход

Предлагаемые цели следующие: придерживаться правила PSR-0 о том, что все пакеты должны содержать как минимум два уровня пространства имен (vendor и package), убедиться, что комбинирование vendor-package может отображаться в любую папку, и разрешить инфикс папок между комбо вендор-пакет и остальная часть полного имени класса.

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

Кроме того, в проекте прямо указывается, что автозагрузчик PSR-4 никогда не должен генерировать исключения или вызывать ошибки просто потому, что может быть зарегистрировано несколько автозагрузчиков, и если один не может загрузить класс, другим следует дать возможность сделать это — выдать ошибку и остановка потока нарушает эту совместимость. Если требуется дополнительная информация о сбое, следует использовать PSR-3- совместимый регистратор или другие произвольные средства.

Как показано в файле примера , использование автозагрузчика PSR-4 для загрузки классов из следующей структуры:

       /path/to/packages/foo-bar/
          src/
              Baz.php             # Foo\Bar\Baz
              Qux/
                  Quux.php        # Foo\Bar\Qux\Quux
          tests/
              BazTest.php         # Foo\Bar\BazTest
              Qux/
                  QuuxTest.php    # Foo\Bar\Qux\QuuxTest

будет выглядеть так:

  <?php
    // instantiate the loader
    $loader = new \Example\Psr4AutoloaderClass;

    // register the autoloader
    $loader->register();

    // register the base directories for the namespace    prefix
    $loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/src');
    $loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/tests');

где вызов new \Foo\Bar\Qux\Quux; будет пытаться загрузить из первого зарегистрированного каталога, в то время как new \Foo\Bar\Qux\QuuxTest; будет пытаться загрузить со второго.

Этот пример также иллюстрирует использование нескольких папок в одном пространстве имен.

Вывод

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

Как вы относитесь к PSR-4? Дайте нам знать в комментариях ниже или выскажите свое мнение в одной из многочисленных дискуссий .

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