До появления PHP Standards Recommendation (PSR) не существовало единых стандартов написания PHP-кода. Например, для стиля кодирования некоторые люди предпочитали стандарт кодирования Zend Framework, некоторые - PEAR Coding Standards, а другие предпочитали создавать свои собственные соглашения об именовании и стиль кодирования.
В 2009 году группа людей, представляющих различные популярные PHP-проекты, собралась вместе и сформировала нечто под названием Framework Interoperability Group (FIG). Цель FIG заключается в том, чтобы представители проектов обсуждали общие черты между своими проектами и находили способы совместной работы.
На данный момент (декабрь 2022 года) принято 14 PSR.
Мы кратко обсудим некоторые из них. Цель этой статьи - познакомить вас с идеями PSR. Для получения более подробной информации о каждом из них, вы всегда можете воспользоваться официальной документацией.
И PSR-0, и PSR-4 являются стандартами для автозагрузки. Если вы не знакомы с автозагрузкой, то это способ включения классов в PHP без написания беспорядочных операторов include/require.
<?php
use Vendor\Package\ClassName;
$object = new ClassName();
PSR-1 и PSR-12 - это стандарты кодирования PHP. PSR-1 фокусируется на основах, в то время как PSR-12 расширяет PSR-1 и предоставляет более полное руководство по стилю кодирования.
PSR-1 содержит набор простых правил для соглашений об именовании и структуры файлов. Его основная цель - обеспечить высокий уровень технической совместимости между общими PHP-кодами. В проекте, в который включены различные пакеты, может возникнуть неразбериха, если каждый из них использует свой стандарт кодирования, именно для решения этой проблемы и был разработан PRS-1. На данный момент стандарты PSR-0 и PSR-2 имеют статус deprecated.
<?php
namespace Vendor\Package;
class ClassName
{
public function fooBarBaz($arg1, &$arg2, $arg3 = [])
{
// method body
}
}
После автозагрузки и стандартов кодирования, мы наконец-то можем связать PSR с PHP кодом. Это PSR-3 и PSR-7. PSR-3 содержит интерфейс логирования, а PSR-7 содержит интерфейсы для HTTP сообщений.
PHP отчаянно нуждался в стандарте для интерфейса логгера до появления PSR-3. Логирование - это настолько распространенная задача, что каждый проект создавал свою собственную версию логгера. Без стандарта, единственным способом использовать сторонний логгер было написать обертку вокруг него, чтобы он мог работать с нашими существующими кодовыми базами. Это был не только болезненный процесс, но и неправильный, потому что, в конце концов, все они выполняли одну и ту же работу: ведение логов. Мы должны иметь возможность выбирать нужный логгер по нашему усмотрению.
PSR-3 предоставляет общий интерфейс для библиотек логирования. Пока они реализуют интерфейс PSR-3 logger, они теоретически должны быть взаимозаменяемы с любыми другими библиотеками PSR-3 logger.
HTTP-сообщения необходимы для веб-приложений. Каждое действие пользователя представляет собой комбинацию HTTP-запроса и HTTP-ответа. PSR-7 предоставляет абстракции вокруг HTTP-сообщений и составляющих их элементов. Он окажет огромное влияние на проекты, которые реализуют детали HTTP сообщений, так как HTTP является довольно сложной темой и большинство вендоров имеют свою собственную реализацию, это много рефакторинга для вендоров, чтобы адаптировать PSR-7.
Как пользователь HTTP сообщений, мы теперь можем работать с HTTP сообщениями универсально благодаря PSR-7. Как и PSR-3, PSR-7 значительно облегчает нашу жизнь при создании многократно используемой кодовой базы.
Этот документ описывает общий интерфейс для контейнеров инъекции зависимостей (dependency injection).
Целью ContainerInterface является стандартизация того, как фреймворки и библиотеки используют контейнер для получения объектов и параметров (называемых в остальной части этого документа элементами).
Ключевые слова "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY" и "OPTIONAL" в этом документе должны интерпретироваться так, как описано в RFC 2119.
Слово "реализатор" в этом документе следует понимать как того, кто имплементирует интерфейс ContainerInterface в библиотеке или фреймворке, связанном с инъекцией зависимостей.
Идентификатор записи - это любая PHP-легальная строка, состоящая как минимум из одного символа, которая однозначно идентифицирует элемент внутри контейнера. Идентификатор записи - это непрозрачная строка, поэтому вызывающие стороны НЕ ДОЛЖНЫ предполагать, что структура строки несет какой-либо семантический смысл.
Чтение из контейнера Psr\Container\ContainerInterface раскрывает два метода: get и has.
get принимает один обязательный параметр: идентификатор записи, который ДОЛЖЕН быть строкой. get может вернуть что угодно (смешанное значение), или выдать NotFoundExceptionInterface, если идентификатор не известен контейнеру. Два последовательных вызова get с одним и тем же идентификатором ДОЛЖНЫ возвращать одно и то же значение. Однако, в зависимости от дизайна исполнителя и/или конфигурации пользователя, могут быть возвращены разные значения, поэтому пользователь НЕ ДОЛЖЕН полагаться на получение одного и того же значения при двух последовательных вызовах.
has принимает один уникальный параметр: идентификатор записи, который ДОЛЖЕН быть строкой. has ДОЛЖЕН возвращать true, если идентификатор записи известен контейнеру, и false, если нет. Если has($id) возвращает false, get($id) ДОЛЖЕН выбросить NotFoundExceptionInterface.
Пользователи НЕ ДОЛЖНЫ передавать контейнер в объект, чтобы объект мог получить свои собственные зависимости. Это означает, что контейнер используется в качестве локатора сервисов, что обычно не рекомендуется.
Диспетчеризация событий - это распространенный и хорошо проверенный механизм, позволяющий разработчикам легко и последовательно внедрять логику в приложение.
Целью данного PSR является создание общего механизма для расширения и взаимодействия на основе событий, чтобы библиотеки и компоненты могли более свободно использоваться в различных приложениях и системах.
Ключевые слова "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY" и "OPTIONAL" в этом документе должны интерпретироваться так, как описано в RFC 2119.
Наличие общих интерфейсов для диспетчеризации и обработки событий позволяет разработчикам создавать библиотеки, которые могут взаимодействовать со многими фреймворками и другими библиотеками в едином ключе.
Некоторые примеры:
События - это объекты, которые выступают в качестве единицы связи между эмиттером и соответствующими слушателями.
Объекты событий МОГУТ быть изменяемыми, если в случае использования требуется, чтобы Слушатели предоставляли информацию обратно к Эмиттеру. Однако если такая двунаправленная коммуникация не требуется, то РЕКОМЕНДУЕТСЯ, чтобы событие было определено как неизменяемое; т.е. определено таким образом, что оно не имеет методов мутатора.
Реализаторы ДОЛЖНЫ предполагать, что один и тот же объект будет передаваться всем Слушателям.
РЕКОМЕНДУЕТСЯ, но НЕ ОБЯЗАТЕЛЬНО, чтобы объекты Event поддерживали сериализацию и десериализацию без потерь; $event == unserialize(serialize($event)) ДОЛЖНО быть верным. Объекты МОГУТ использовать интерфейс Serializable PHP, магические методы __sleep() или __wakeup(), или аналогичную функциональность языка, если это уместно.