Psr php что это
PSR Стандарты
PSR — Чуть больше, чем стиль оформления кода.
Как показала практика, многие PHP-разработчики знакомы с аббревиатурой PSR. Однако большинство все еще ограничены знанием, что PSR это стандарт оформления кода.
Ребята из PHP-FIG (PHP Framework Interop Group), группа концепций совместимости PHP, которые занимаются развитием PSR (PHP Standards Recommendations) шагнули далеко вперед. Поэтому давайте разберемся, что из себя представляет PSR…
За последние полгода мне пришлось провести множество собеседований на позицию Middle PHP-Developer.
Один из вопросов, который я задавал всем кандидатам, был:- «Знаете ли Вы, что такое PSR?»
Как оказалось, практически всем кандидатам была знакома эта аббревиатура. Однако пытаясь рассказать подробнее, почти все разработчики указывали в основном на то, что это стандарт оформления кода (code style). Только некоторые упоминали про PSR-4 автозагрузку (использует Composer) и PSR-3 Logger Interface (в сети очень много однородных статей про PSR-0-1-2-3-4).
Мне кажется это весьма странным, так как термин PSR существует достаточно давно (уже более 10 лет) и каждый год набирает все большую популярность. Поэтому, думаю, будет неплохо собрать все в кучу и сделать обзор PSR стандартов.
PHP-FIG и PSR
PHP-FIG (PHP Framework Interop Group) — организованная в 2009 году группа разработчиков, основная идея которой находить способы совместной работы, выделяя общие концепции в разработке проектов на PHP.
Проще говоря, ребята стараются выделить что-то общее между различными проектами на разных фреймворках и сформировать некие стандарты (рекомендации) для дальнейшего периспользования.
Участники PHP-FIG
ReactPHP, Composer, Laminas Project (переименованный Zend Framework), Yii framework, CakePHP, Slim, Joomla, Magento, Drupal, phpBB, phpDocumentor и другие.
PSR (PHP Standards Recommendations) — описывает общие концепции, которые уже были проверены и отработаны. Вероятно при создании PSR, группа PHP-FIG вдохновлялась Java Community Process, а первый стандарт был принят в 2010 году.
Список PSR стандартов расширяется новыми, а сами стандарты делятся на категории:
Автозагрузка, Интерфейсы, HTTP и Стиль кодирования,
каждому из которых присваивается определенный статус:
Принят, Устаревший, Черновик и Заброшенный.
Далее мы рассмотрим принятые PSR стандарты по категориям:
Автозагрузка
Разработчики, которые «недолго» работают с PHP, вероятно не знакомы с проблемами импорта классов, ведь есть пространства имен, а сейчас вообще трудно представить проект без менеджера зависимостей Composer, которой решает все вопросы с автозагрузкой классов.
Однако так было не всегда, пространства имен появились только в PHP 5.3 (это был 2009 год), а первый релиз Composer состоялся в марте 2012 года. Но вот сам PHP существует гораздо дольше, как Personal Home Page с 1995 года и как Hypertext Preprocessor с 1998 года, однако только PHP 5 включает «полноценную объектную модель», релиз которого был в июле 2004 года. Бородатым разработчикам того времени приходилось как-то сражаться со всеми возникшими проблемами при импорте классов.
Не самый плохой пример импорта классов на PHP 14-ти летней давности:
(Напишите в комментариях, если узнали где использовался данный подход).
В дополнение, оставлю ссылку на статью, которая подробно описывает работу с пространством имен, решенные проблемы и PSR-4.
Интерфейсы
PHP развивается, набирает все большую популярность, а его инфраструктура пополняется огромным количеством различных инструментов.
Появляются проблемы с изучением и переиспользованием однотипного функционала, а менеджер зависимостей может затянуть целую кучу несвязанных однотипных зависимостей. (тут JavaScript разработчик улыбнется).
Поэтому принято решение стандартизировать некоторые общие концепции:
Если Ваш проект нуждается в расширенном функционале, МОЖНО расширять данный интерфейс, но СЛЕДУЕТ сохранять совместимость с описанными в данном стандарте правилами. Это позволит сторонним библиотекам, применяемых при разработке приложения, использовать централизованную систему логирования.
Это привело к ситуации, когда многие библиотеки реализуют свои собственные системы кэширования с различными уровнями функциональности. Эти различия заставляют разработчиков изучать несколько систем, которые могут предоставлять или не предоставлять необходимую им функциональность. Кроме того, разработчики кеширующих библиотек сами сталкиваются с выбором между поддержкой только ограниченного числа платформ или созданием большого количества классов адаптеров.
Чтобы решить эти проблемы был принят общий стандарт для библиотек реализующих кэширование, он включает в себя несколько интерфейсов:
Пользователи НЕ ДОЛЖНЫ передавать контейнер в объект, чтобы объект мог получить свои собственные зависимости. Это означает, что контейнер используется в качестве Service Locator, который обычно не рекомендуется использовать.
Отсюда, возникает простой вопрос: «Как это вообще работает»?
На самом деле все просто, на помощь приходит паттерн Factory, который возьмет на себя задачу создания объекта. А вот сам класс фабрики уже может принимать ContainerInterface и передавать в создаваемый объект необходимые зависимости.
Поэтому был принят PSR-16. Этот более простой подход направлен на создание стандартизированного оптимизированного интерфейса для общих случаев.
В списке реализаций все тот-же Symfony Cache и Laminas Cache (бывший Zend).
Если речь идет о WEB-приложении, то не важно на сколько сложная в нем бизнес-логика, по факту оно делает всего 2 вещи — принимает Request и отдает Response. Это значит, что так или иначе, приходится реализовывать эти объекты у себя в проекте.
Пожалуй, одной из самых сложных задач, которая нередко возникает является переиспользование кода между различными проектами. Если хорошо абстрагированные участки бизнес логики, некоторые компоненты и модули перенести возможно (с минимальными затратами), то с переносом более высокого уровня фреймворков (например контроллеров) возникают сложности.
Группа PHP-FIG пытается исправить данную проблему и предоставляет стандарты абстракции над HTTP.
А более детальное описание с примерами можно разобрать в статье «PSR-7 в примерах».
Если не вдаваться во все тонкости, то по сути это возможность писать некие абстрактные контроллеры для последующего переиспользования между различными проектами.
PSR-7 не содержит рекомендации о том, как создавать HTTP-объекты. Это может приводить к трудностям при необходимости их создания внутри компонентов, которые не привязаны к конкретной реализации PSR-7.
Интерфейсы, описанные в этой спецификации, описывают методы, с помощью которых можно создавать PSR-7 объекты.
Это может сделать библиотеки более пригодными для повторного использования, так как уменьшает количество зависимостей и снижает вероятность конфликтов версий.
Также в спецификации указано, что HTTP-клиенты могут быть заменены согласно принципу подстановки Лисков. Это означает, что все клиенты ДОЛЖНЫ вести себя одинаково при отправке запроса.
Пример реализации PSR-18 можно увидеть в библиотеке Symfony HTTP-client.
Предложенная абстракция над HTTP — это весьма серьезная заявка на попытку реализовывать действительно переиспользуемые и не зависящие от конкретных библиотек и фреймворков полноценные решения.
На практике, конечно все на много сложнее и есть свои нюансы и подводные камни, однако PHP-FIG делает значительный шаг вперед в этом направлении.
Стиль кодирования
До появления стандартов стиля кодирования, каждый из разработчиков оформлял свой код по-разному: одни писали CLASSNAME, другие ClassName, а третьи Class_Name, вечный спор относительно табов и пробелов, а еще StudlyCaps vs сamelCase vs snake_case и так далее.
Цель следующих PSR стандартов уменьшить когнитивное искажение при чтении кода от разных авторов.
PHP: Стандарты кодирования
Стандарт PSR-1. Основной стандарт кодирования
PSR-2. Стиль кодирования
Список аргументов функции МОЖНО разбить на несколько строк, каждая из которых с одним отступом. При этом первый аргумент в списке НЕОБХОДИМО перенести на следующую строку, и в каждой строке НЕОБХОДИМО указать только один аргумент.
12) while, do-while, for, foreach
Классы
1) Открывающие фигурные скобки классов НЕОБХОДИМО переносить на следующую строку, а закрывающие фигурные скобки переносить на следующую строку после тела.
2) Видимость НЕОБХОДИМО объявлять для всех свойств и методов (public, private. )
3) НЕОБХОДИМО оставлять одну пустую строку после объявления пространства имён (namespace) и НЕОБХОДИМО оставлять одну пустую строку после блока операторов use.
4) Ключевые слова extends и implements НЕОБХОДИМО располагать на одной строке с именем класса. Список implements МОЖНО разбить на несколько строк, каждая из которых с одним отступом. При этом первый интерфейс в списке НЕОБХОДИМО перенести на следующую строку, и в каждой строке НЕОБХОДИМО указать только один интерфейс.
5) НЕ СЛЕДУЕТ начинать название метода или свойства с подчёркивания для обозначения приватной или защищённой видимости.
6) НЕДОПУСТИМО в одном объявлении видимости указывать более одного свойства.
7) НЕДОПУСТИМО объявлять методы с пробелом после названия метода. Открывающую фигурную скобку НЕОБХОДИМО располагать на отдельной строке; закрывающую фигурную скобку НЕОБХОДИМО располагать на следующей строке после тела метода. НЕДОПУСТИМО оставлять пробел после открывающей круглой скобки и перед закрывающей.
В списке аргументов метода НЕДОПУСТИМЫ пробелы перед запятыми и НЕОБХОДИМ один пробел после каждой запятой.
8) Список аргументов МОЖНО разбить на несколько строк. Когда список аргументов разбит на несколько строк, закрывающую круглую скобку и открывающую фигурную НЕОБХОДИМО располагать на одной отдельной строке, с одним пробелом между ними.
9) При наличии ключевых слов abstract и final, НЕОБХОДИМО чтобы они предшествовали модификаторам видимости. При наличии ключевого слова static, НЕОБХОДИМО чтобы оно следовало за модификатором видимости.
10) Анонимные функции умышленно упущены в данной статье по той причине, что курс обходит их стороной. Но никто не мешает почитать.
PSR Стандарты
PSR — Чуть больше, чем стиль оформления кода.
Как показала практика, многие PHP-разработчики знакомы с аббревиатурой PSR. Однако большинство все еще ограничены знанием, что PSR это стандарт оформления кода.
Ребята из PHP-FIG (PHP Framework Interop Group), группа концепций совместимости PHP, которые занимаются развитием PSR (PHP Standards Recommendations) шагнули далеко вперед. Поэтому давайте разберемся, что из себя представляет PSR…
За последние полгода мне пришлось провести множество собеседований на позицию Middle PHP-Developer.
Один из вопросов, который я задавал всем кандидатам, был:- «Знаете ли Вы, что такое PSR?»
Как оказалось, практически всем кандидатам была знакома эта аббревиатура. Однако пытаясь рассказать подробнее, почти все разработчики указывали в основном на то, что это стандарт оформления кода (code style). Только некоторые упоминали про PSR-4 автозагрузку (использует Composer) и PSR-3 Logger Interface (в сети очень много однородных статей про PSR-0-1-2-3-4).
Мне кажется это весьма странным, так как термин PSR существует достаточно давно (уже более 10 лет) и каждый год набирает все большую популярность. Поэтому, думаю, будет неплохо собрать все в кучу и сделать обзор PSR стандартов.
PHP-FIG и PSR
PHP-FIG (PHP Framework Interop Group) — организованная в 2009 году группа разработчиков, основная идея которой находить способы совместной работы, выделяя общие концепции в разработке проектов на PHP.
Проще говоря, ребята стараются выделить что-то общее между различными проектами на разных фреймворках и сформировать некие стандарты (рекомендации) для дальнейшего периспользования.
Участники PHP-FIG
ReactPHP, Composer, Laminas Project (переименованный Zend Framework), Yii framework, CakePHP, Slim, Joomla, Magento, Drupal, phpBB, phpDocumentor и другие.
PSR (PHP Standards Recommendations) — описывает общие концепции, которые уже были проверены и отработаны. Вероятно при создании PSR, группа PHP-FIG вдохновлялась Java Community Process, а первый стандарт был принят в 2010 году.
Список PSR стандартов расширяется новыми, а сами стандарты делятся на категории:
Автозагрузка, Интерфейсы, HTTP и Стиль кодирования,
каждому из которых присваивается определенный статус:
Принят, Устаревший, Черновик и Заброшенный.
Далее мы рассмотрим принятые PSR стандарты по категориям:
Автозагрузка
Разработчики, которые «недолго» работают с PHP, вероятно не знакомы с проблемами импорта классов, ведь есть пространства имен, а сейчас вообще трудно представить проект без менеджера зависимостей Composer, которой решает все вопросы с автозагрузкой классов.
Однако так было не всегда, пространства имен появились только в PHP 5.3 (это был 2009 год), а первый релиз Composer состоялся в марте 2012 года. Но вот сам PHP существует гораздо дольше, как Personal Home Page с 1995 года и как Hypertext Preprocessor с 1998 года, однако только PHP 5 включает «полноценную объектную модель», релиз которого был в июле 2004 года. Бородатым разработчикам того времени приходилось как-то сражаться со всеми возникшими проблемами при импорте классов.
Не самый плохой пример импорта классов на PHP 14-ти летней давности:
(Напишите в комментариях, если узнали где использовался данный подход).
В дополнение, оставлю ссылку на статью, которая подробно описывает работу с пространством имен, решенные проблемы и PSR-4.
Интерфейсы
PHP развивается, набирает все большую популярность, а его инфраструктура пополняется огромным количеством различных инструментов.
Появляются проблемы с изучением и переиспользованием однотипного функционала, а менеджер зависимостей может затянуть целую кучу несвязанных однотипных зависимостей. (тут JavaScript разработчик улыбнется).
Поэтому принято решение стандартизировать некоторые общие концепции:
Если Ваш проект нуждается в расширенном функционале, МОЖНО расширять данный интерфейс, но СЛЕДУЕТ сохранять совместимость с описанными в данном стандарте правилами. Это позволит сторонним библиотекам, применяемых при разработке приложения, использовать централизованную систему логирования.
Это привело к ситуации, когда многие библиотеки реализуют свои собственные системы кэширования с различными уровнями функциональности. Эти различия заставляют разработчиков изучать несколько систем, которые могут предоставлять или не предоставлять необходимую им функциональность. Кроме того, разработчики кеширующих библиотек сами сталкиваются с выбором между поддержкой только ограниченного числа платформ или созданием большого количества классов адаптеров.
Чтобы решить эти проблемы был принят общий стандарт для библиотек реализующих кэширование, он включает в себя несколько интерфейсов:
Пользователи НЕ ДОЛЖНЫ передавать контейнер в объект, чтобы объект мог получить свои собственные зависимости. Это означает, что контейнер используется в качестве Service Locator, который обычно не рекомендуется использовать.
Отсюда, возникает простой вопрос: «Как это вообще работает»?
На самом деле все просто, на помощь приходит паттерн Factory, который возьмет на себя задачу создания объекта. А вот сам класс фабрики уже может принимать ContainerInterface и передавать в создаваемый объект необходимые зависимости.
Поэтому был принят PSR-16. Этот более простой подход направлен на создание стандартизированного оптимизированного интерфейса для общих случаев.
В списке реализаций все тот-же Symfony Cache и Laminas Cache (бывший Zend).
Если речь идет о WEB-приложении, то не важно на сколько сложная в нем бизнес-логика, по факту оно делает всего 2 вещи — принимает Request и отдает Response. Это значит, что так или иначе, приходится реализовывать эти объекты у себя в проекте.
Пожалуй, одной из самых сложных задач, которая нередко возникает является переиспользование кода между различными проектами. Если хорошо абстрагированные участки бизнес логики, некоторые компоненты и модули перенести возможно (с минимальными затратами), то с переносом более высокого уровня фреймворков (например контроллеров) возникают сложности.
Группа PHP-FIG пытается исправить данную проблему и предоставляет стандарты абстракции над HTTP.
А более детальное описание с примерами можно разобрать в статье «PSR-7 в примерах».
Если не вдаваться во все тонкости, то по сути это возможность писать некие абстрактные контроллеры для последующего переиспользования между различными проектами.
PSR-7 не содержит рекомендации о том, как создавать HTTP-объекты. Это может приводить к трудностям при необходимости их создания внутри компонентов, которые не привязаны к конкретной реализации PSR-7.
Интерфейсы, описанные в этой спецификации, описывают методы, с помощью которых можно создавать PSR-7 объекты.
Это может сделать библиотеки более пригодными для повторного использования, так как уменьшает количество зависимостей и снижает вероятность конфликтов версий.
Также в спецификации указано, что HTTP-клиенты могут быть заменены согласно принципу подстановки Лисков. Это означает, что все клиенты ДОЛЖНЫ вести себя одинаково при отправке запроса.
Пример реализации PSR-18 можно увидеть в библиотеке Symfony HTTP-client.
Предложенная абстракция над HTTP — это весьма серьезная заявка на попытку реализовывать действительно переиспользуемые и не зависящие от конкретных библиотек и фреймворков полноценные решения.
На практике, конечно все на много сложнее и есть свои нюансы и подводные камни, однако PHP-FIG делает значительный шаг вперед в этом направлении.
Стиль кодирования
До появления стандартов стиля кодирования, каждый из разработчиков оформлял свой код по-разному: одни писали CLASSNAME, другие ClassName, а третьи Class_Name, вечный спор относительно табов и пробелов, а еще StudlyCaps vs сamelCase vs snake_case и так далее.
Цель следующих PSR стандартов уменьшить когнитивное искажение при чтении кода от разных авторов.
Стандарты PSR
Язык программирования PHP прошел большой путь от инструмента для создания персональных страниц до языка общего назначения. Сегодня он установлен на миллионах серверов по всему миру, используется миллионами разработчиков, которые создают множество самых разнообразных проектов.
Он прост в изучении и крайне популярен, особенно среди новичков. Поэтому вслед за развитием языка последовало и мощное развитие сообщества вокруг него. Огромное количество скриптов, на все случаи жизни, разные библиотеки, фреймворки. Отсутствие же единых норм оформления и написания кода, привели к возникновению огромного пласта информационных продуктов построенных на собственных принципах разработчика этого продукта. Особенно это было заметно при работе с различным PHP фреймворками, которые долгое время представляли собой замкнутую экосистему, не совместимую с другими фреймворками, несмотря на то, что задачи, которые решаются ими часто схожи.
В 2009 году разработчики нескольких фреймворков договорились о создании сообщества PHP Framework Interop Group (PHP-FIG), которое бы вырабатывало рекомендации для разработчиков. Важно подчеркнуть, что речь не идет о ISO-стандартах, более правильно говорить о рекомендациях. Но так как создавшие PHP-FIG сообщество разработчики представляют крупные фреймворки, то их рекомендации представляют серьёзный вес. Поддержка PSR (PHP standart recommendation) стандартов позволяет обеспечивать совместимость, что облегчает и ускоряет разработку конечного продукта.
Всего на момент написания статьи существует 17 стандартов, причем 9 из них являются утвержденными, 8 находятся в стадии проекта, активно обсуждаются, 1 стандарт не рекомендован к использованию.
Теперь перейдем непосредственно к описанию каждого стандарта. Заметьте, что я не буду здесь подробно разбирать каждый стандарт, скорее это небольшое введение. Также в статье будут рассматриваться только те стандарты PSR, которые официально приняты, т.е. находятся в статусе Accepted.
PSR-1. Основной стандарт кодирования
Он представляет собой наиболее общие правила, такие как, например, использование тегов PHP, кодировка файлов, разделения места объявления функции, класса и места их использования, именование классов, методов.
PSR-2. Руководство по стилю кода
Является продолжением первого стандарта и регулирует вопросы использования в коде табуляции, переводов строк, максимальную длину строк кода, правила оформления управляющих конструкций и т.д.
PSR-3. Интерфейс протоколирования.
Этот стандарт разработан для того, чтобы обеспечить (журналирование) логирование в приложениях, написанных на PHP.
PSR-4. Стандарт автозагрузки
Это, наверное, самый важный и нужный стандарт, которому будет посвящена отдельная, подробная статья. Классы, которые реализуют PSR-4, могут быть загружены единым автозагрузчиком, что позволяет частям и компонентам из одного фреймворка или библиотеки быть использованными в других проектах.
PSR-6. Интерфейс кеширования
Кэширование используется для повышения производительности системы. И PSR-6 позволяет стандартно сохранять и извлекать данные из кэша, используя унифицированный интерфейс.
PSR-7. Интерфейс HTTP-сообщений
PSR-11. Интерфейс контейнера
При написании PHP программы часто приходится использовать сторонние компоненты. И чтобы не заблудиться в этом лесу зависимостей были придуманы различные методы управления зависимостями кода, зачастую несовместимые между собой, которые данный стандарт и приводит к общему знаменателю.
PSR-13. Гипермедиа ссылки
Данный интерфейс призван облегчить разработку и использование прикладных программных интерфейсов (API).
PSR-14. Интерфейс простого кэширования
Является продолжением и улучшением стандарта PSR-6
Таким образом, сегодня мы с Вами рассмотрели PSR стандарты. За актуальной информацией о статусе стандартов можете обращаться по адресу PHP-FIG.
Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!
Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления
Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
Комментарии ( 0 ):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.
Copyright © 2010-2021 Русаков Михаил Юрьевич. Все права защищены.
PSR-7 в примерах
Стандарт PSR-7 успешно завершён. На этой неделе были добавлены последние штрихи. И теперь версия 0.6.0 пакета http-message package готова к использованию. Попробуйте следовать этому стандарту в своих приложениях.
Я до сих пор слышу замечания как по поводу слишком упрощённого, так и по поводу слишком сложного изложения. Именно поэтому написан этот пост — чтобы продемонстрировать использование опубликованных рекомендаций и показать одновременно и их простоту, и полноту и надёжность, которые они предоставляют.
Для начала, я кратко расскажу о том, что регулирует этот стандарт.
HTTP сообщения
HTTP — достаточно простой протокол. Именно поэтому он успешно используется на протяжении многих лет. Сообщения в нём имеют следующую структуру:
Заголовки представляют собой пары ключ–значение. Ключи являются чувствительными к регистру. Значения представляют собой строки. Один заголовок может иметь несколько значений. В этом случае обычно значения представлены списком, разделённым запятыми.
Тело сообщения (Message body) – это строка. Хотя обычно оно обрабатывается сервером и клиентом как поток, чтобы уменьшить потребление памяти и снизить нагрузку при обработке. Это чрезвычайно важно, когда передаются большие наборы данных, и особенно, когда передаются файлы. Например, PHP «из коробки» представляет входящее тело запроса как поток php://input и использует выходной буфер (тоже, формально, поток), чтобы вернуть ответ.
Строка сообщения (message line) – это место, которое отличает HTTP запрос от ответа.
Строка сообщения у запроса (далее строка запроса) имеет следующий формат:
“scheme” в http запросе будет или http, или https. “path” – это тоже всем понятная часть. Но что такое “authority”?
“authority” всегда содержит хост, который может быть доменным именем или IP адресом. Порт является опциональным и необходим только в том случае, когда не является стандартным для данной схемы (или если схема неизвестна). Информация о пользователе представляется в виде
где пароль является необязательным. Фактически, в существующих спецификациях, рекомендуется вообще не использовать пароль в URI. Лучше принудительно запросить пароль у клиента.
Строка запроса – это набор пар ключ-значение, разделённых амперсандами:
В зависимости от языка реализации, она так же может моделировать списки или массивы:
PHP преобразует данную строку в двумерный массив:
Итак, если бы гибкости в формировании цели запроса нам оказалось бы недостаточно, URI предоставил бы свою.
К счастью, ответы HTTP сервера проще. Строка ответа выглядит следующим образом:
“VERSION”, как говорилось ранее, — это обычно 1.0 или, чаще, 1.1. “status” – это число от 100 до 599 включительно; «reason» — пояснение к статусу, стандартное для каждого статуса.
Итак, это был беглый обзор HTTP сообщений. Давайте теперь посмотрим, как PSR-7 моделирует их.
Заголовки сообщений
Вся вышеуказанная логика не зависит от того, как указан заголовок; accept, ACCEEPT или даже aCCePt будут корректными именами заголовка и вернут одинаковый результат.
PSR-7 предполагает, что разбор всех заголовков вернёт структуру в виде массива:
Когда структура определена, пользователи точно будут знать, что получат и могут обрабатывать заголовки удобным им способом – вне зависимости от реализации.
Но что если вы захотите добавить заголовки к сообщению – например, чтобы создать запрос и передать его HTTP клиенту?
Сообщения в PSR-7 смоделированы в виде объектов-значений; это означает, что любое изменение в состоянии – это, фактически, другое значение. Таким образом, определение нового заголовка создаст в результате новый объект сообщения.
Если вам нужно просто обновить значение, вы можете просто переопределить его:
Если вы хотите добавить другое значение к уже существующему заголовку, вы можете поступить следующим образом:
Или даже удалить заголовок:
Тело сообщения
Как было указано выше, тело сообщения обычно обрабатывается как поток для улучшения производительности. Это особенно важно, когда вы передаёте файлы, используя HTTP. Если только вы не собираетесь использовать всю доступную память на текущий процесс. Большинство реализаций HTTP сообщений, которые я просмотрел, забывают об этом или пытаются изменить поведение по факту (да, даже ZF2 этим грешит!). Если вы хотите подробнее прочитать о преимуществах данного подхода, прочитайте статью Майкла Доулинга. Он написал в своём блоге об использовании потоков в PSR-7 прошлым летом.
Итак, тело сообщения в PSR-7 смоделировано как поток.
«Но это слишком сложно для 80% случаев, где можно обойтись строками!» — наиболее частый аргумент в числе тех, что критикуют данную реализацию обработки тела сообщения. Хорошо, давайте рассмотрим следующее:
Данный пример, и все последующие примеры работы с HTTP сообщениями в данном посте будут использовать phly/http – библиотеку, написанную мной и отражающую развитие PSR-7. В данном случае Stream реализует StreamableInterface.
По существу, вы получаете тонкий, объектно-ориентированный интерфейс для взаимодействия с телом сообщения, который позволяет добавить к нему информацию, прочитать её и многое другое. Хотите изменить сообщение? Создайте новое тело сообщения:
Моё мнение состоит в том, что несмотря на то, что представление тела сообщения в виде потока кажется сложным, на деле реализация и использование достаточно просты и понятны.
Выгода использования StreamableInterface в PSR-7 состоит в том, что он предоставляет гибкость, упрощающую реализацию различных шаблонов проектирования. Например, вы можете реализовать “callback” функцию, которая при вызове метода read() или getContents() возвращает содержание сообщения (Drupal, в частности, использует этот шаблон). Или «Iterator», реализация которого использует любой «Traversable», чтобы вернуть или объединить контент. Смысл в том, что такой интерфейс даёт вам широкий простор реализации множества шаблонов для работы с телом сообщения. А не ограничивает просто строками или файлами.
StreamableInterface предлагает набор методов, которые чаще всего используются при работе с телом HTTP сообщения. Это не означает, что он предусматривает абсолютно всё, но покрывает большой набор потенциально необходимых операций.
Лично я люблю использовать потоки php://temp, потому как они находятся в памяти до тех пор, пока не станут достаточно большими (в этом случае они записываются во временный файл на диске). Метод может быть достаточно эффективным.
Ответы
До сих пор мы рассматривали функции, общие для любых сообщений. Теперь я собираюсь остановиться на ответах в частности.
У ответа есть статус код и пояснительная фраза:
Это легко запомнить. Теперь, что если мы сами формируем ответ?
Пояснительная фраза считается необязательной (но в тоже время стандартной для каждого статус кода). Для неё интерфейс предусматривает специфичный для ответа мутатор withStatus():
Повторюсь, сообщения смоделированы как объекты-значения; изменение любого значения создаст в результате новый экземпляр, который должен быть привязан к ответу или запросу. Но в большинстве случаев вы будете просто переназначать текущий экземпляр.
Запросы
$uri в данном случае будет экземпляром UriInterface, и позволит вам использовать URI:
Точно так же, как и HTTP сообщения, URI представлены в виде объектов-значений, и изменение любой части URI меняет его значение, мутирующие методы возвращают новый экземпляр:
Так как изменение URI означает создание нового экземпляра, то если вы хотите, чтобы изменение отразились в вашем запросе, вам необходимо сообщить об этих изменениях объекту запроса; и, как и с любым сообщением, если необходимо изменить метод или URI в конкретном экземпляре, следует использовать следующие методы:
Серверные запросы
Представим, что вы пишете API и хотите принимать запросы в формате JSON; выполнение этого может выглядеть следующим образом:
Пример выше демонстрирует несколько функций. Во-первых, он показывает извлечение заголовка из запроса, и ветвление логики, основанное на этом заголовке. Во-вторых, он показывает формирование объекта запроса в случае ошибки (функция emit() является гипотетической, она принимает объект запроса и отдаёт заголовки и тело запроса). Наконец, пример демонстрирует получение тела запроса, десериализацию и внедрение его снова в запрос.
Атрибуты
Экземпляр запроса в данном случае используется для упорядочивания данных и передачи маршруту. Затем результаты маршрутизации используются для создания экземпляра ответа.
Варианты использования
Теперь после быстрой экскурсии по различным компонентам PSR-7, давайте вернёмся к конкретным примерам использования.
Клиенты
Для меня главным создателем стандарта PSR-7 является Майкл Доулинг, автор популярного HTTP клиента Guzzle. Поэтому совершенно очевидно, что PSR-7 принесёт улучшения HTTP клиентам. Давайте обсудим как.
Во-первых, это означает, что разработчики будут иметь уникальный интерфейс сообщений для выполнения запросов; они могут отправлять объект запроса по стандарту PSR-7 клиенту и получать обратно объект ответа по тому же стандарту.
Благодаря тому, что сообщения и URI смоделированы как объекты-значения, это так же означает, что разработчики могут создавать базовые экземпляры запросов и URI и создавать раздельные запросы и URI из них:
Что PSR-7 предлагает, так это стандартный способ взаимодействия с запросами, которые вы отправляете клиентом, и ответами, которые получаете. Реализуя объекты-значения, мы открываем возможность некоторым интересным вариантам использования с прицелом на упрощение шаблона «сброс запроса» — изменение запроса всегда даёт в результате новый экземпляр, позволяя нам иметь базовый экземпляр с известным состоянием, который мы всегда можем расширить.
Связующее звено
Я не буду долго на этом останавливаться, т.к. уже делал это в статье. Основная идея, если кратко, состоит в следующем:
Функция принимает два HTTP сообщения, и выполняет некоторые преобразования с ними (которые могут включать делегирование к следующему доступному связующему звену). Обычно эти звенья возвращают объект ответа.
Другой вариант, который часто используется – это лямбда выражения (спасибо Ларри Гарфилду, который выслал мне на почту этот термин!):
В лямбда звене вы составляете одно в другом:
И наконец, есть метод, продвигаемый Rack и WSGI, в котором каждое звено является объектом и проходит к выходу:
Использование промежуточного звена состоит в том, что оно реализует связь между запросом и ответом и следует стандарту: предсказуемый шаблон с предсказуемым поведением. Это отличный метод написания веб компонентов, которые могут быть переиспользованы.
Фреймворки
Одна вещь, которую фреймворки предлагают на протяжении многих лет – это … слой абстракции над HTTP сообщениями. Цель PSR-7 предоставить общий набор интерфейсов для фреймворков, чтобы последние могли использовать одинаковые абстракции. Это позволит разработчикам писать переиспользуемый, независимый от фреймворка код или, по крайней мере, это то, что я хотел бы увидеть!
Рассмотрим Zend Framework 2. Он определяет интерфейс Zend\Stdlib\DispatchableInterface, который является базовым для любого контроллера, который вы собираетесь использовать в фреймворке:
Это как раз описанное нами выше промежуточное звено; одно единственное различие состоит в том, что оно использует специфичные для данного фреймворка реализации HTTP сообщений. Что если вместо этого оно будет поддерживать PSR-7?
Большинство реализаций HTTP сообщений в фреймворках построено таким образом, что вы можете изменить состояние сообщения в любое время. Иногда это может быть не совсем верно, особенно если допустить, что состояние сообщения может быть уже недействительно. Но это, пожалуй, единственный недостаток данного метода.
Сообщения по стандарту PSR-7 являются объектами-значениями. Таким образом, вам не потребуется сообщать приложению каким-либо образом о любом изменении в сообщениях. Это делает реализацию более явной и простой для отслеживания в вашем коде (и пошагово в отладчике, и с использованием статических анализаторов кода).
В качестве примера, если ZF2 будет обновлён в соответствии с PSR-7, разработчики не будут обязаны сообщать MvcEvent о любых изменениях, которые они хотят передать сдедующим клиентам:
Приведённый выше код ясно показывает, что мы меняем состояние приложения.
Использование объектов-значений делает более простой одну особенную практику: распределение подзапросов или реализация Hierarchical MVC (HMVC). В этом случае вы можете создавать новые запросы, основанные на текущем, без информирования об этом приложения, и будучи уверенными, что состояние приложения не изменится.
В общем, для большинства фреймворков, использование PSR-7 сообщений переведёт к переносимой абстракции над HTTP сообщениями. Это даст возможность реализовать универсальное промежуточное звено. Адаптация сообщений, однако, потребует незначительных изменений. Разработчикам необходимо обновить код, отвечающий за отслеживание состояния приложения.