Специальный выпуск, посвящённый PSR-7.
Всем привет!
Вы слушаете «Пятиминутку PHP», выпуск номер 2 — еженедельный подкаст о новостях из мира PHP, интересных постах в блогах и современных подходах к разработке.
Это специальный выпуск, посвящённый PSR-7.
Итак, 18 мая принят стандарт PSR-7 — HTTP Message Interface — набор PHP интерфейсов, описывающих HTTP запрос и HTTP ответ.
Напомню историю вопроса. В старые-добрые времена PHP разработчики использовали суперглобальные переменные $_GET, $_POST, $_SERVER, $_FILES и $_COOKIE для получения информации о пришедшем запросе. А для отправки ответа в браузер использовались такие инструкции как echo и print, для http заголовков встроенная функция header(). При этом все мы помним проблему, что нельзя отправить header уже после того, как сделан вывод в основной поток вывода с помощью print или echo.
Позже стали появляться фреймворки, предоставляющие удобные объектно-ориентированные обёртки над этими суперглобальными переменными — так называемые объекты Request и Response. Объект Request икапсулирует в себе все данные пришедшие от клиента (от браузера пользователя), а объект Response предназначен для наполнения данными отправляемыми в браузер. Более того, современные фреймворки обычно имеют некое ядро приложения, которое на вход принимает объект Request и возвращает Response. Эта абстракция, помимо всего прочего, оказалась очень удобной для написания функциональных тестов: можно сгенерировать много разнообразных объектов Request и потом проверить получившиеся в результате Response, не создавая при этом нагрузки на сеть или каких-либо реальных запросов к веб-серверу.
Аналогичный подход с Request/Response обёртками уже давно используется и в других языках программирования, где он зачастую стандартизирован: Rack для Ruby, WSGI для Python, Java Servlet в Java и стандартный HTTP интерфейс в Node.
В PHP, напротив, чуть ли не каждый фреймворк изобретал свои обёртки и интерфейсы. Самым популярным решением являются компоненты из Symfony, которые используются в микрофреймворке Silex, Laravel, Drupal 8, в системе электронной коммерции Ez, в phpBB и в некоторых других проектах. На сайте Symfony есть отдельная страница со списком пользователей компонента HttpKernel.
В некотором смысле, можно сказать, что в PHP изначально существовал такой же стандартный интерфейс для HTTP запроса – это те самые суперглобальные переменные. Но этот якобы стандарт не очень удобен по ряду причин.
Поэтому, группа энтузиастов PHP-FIG (Framework Interop Group), представленная разработчиками самых популярных фреймворков и CMS-ок, после долгой работы (с 2012 года), представила и приняла новый стандарт PSR-7 — HTTP Message Interface!
В феврале на Хабре была хорошая статья «PSR-7 в примерах». На тот момент стандарт ещё не был утверждён и позже в него были внесены незначительные изменения. Тем не менее рекомендую к прочтению.
На следующий день после принятия, Мэтью (это главный по ZendFramework) описал в своём блоге историю работы над PSR-7, эта статья также есть на Хабре, почитайте.
А я пока расскажу немного деталей в сжатом виде, чтобы уложиться в формат «Пятиминутки PHP».
Итак, набор интерфейсов PSR-7 можно скачать через composer (psr/http-message) или непосредственно с GitHub (https://github.com/php-fig/http-message). Там вы найдёте семь PHP интерфейсов в неймспейсе Psr\Http\Message. Но это только интерфейсы, никакой реализации! Реализацию вам в будущем предоставят фреймворки или вы можете написать свою. Главное — использовать эти интерфейсы, и тогда различные фреймворки смогут быть взаимозаменяемы в вопросах обработки HTTP запросов и ответов.
Одной из особенностей являются так называемые value-objects – неизменяемые объекты. Традиционно в ООП мы имеем объекты, у которых есть методы сеттеры. Сеттеры меняют внутреннее состояние объекта, таким образом эти объекты можно назвать изменяемыми. Но при использовании паттерна value-objects, сеттеры не меняют сам объект, а создают и возвращают его клон, в котором изменено указанное поле. Неизменяемые данные, как общий подход в программировании, с одной стороны кажутся расточительными по памяти и не такими быстрыми, с другой стороны, они смогут снять головную боль от случайных изменений в глубинах кода, ведь объекты передаются по ссылке, и помогают при разработке программ с параллельными вычислениями на разных ядрах процессора или даже на разных процессорах (это больше относится к другим языкам). Если говорить о PHP, который, как мы знаем «создан, чтобы умирать», подход с неизменяемыми данными кажется совсем не очевидным. На эту тему было много дискуссий при разработке стандарта, в итоге пришли к value-objects. Лично я поддерживаю это решение.
Второе, о чём хочется упомянуть, это использование потоков (streams). Тело запроса или ответа может быть большим (мегабайты, и даже гигабайты). Если использовать для тела запроса строковую переменную, то PHP может умереть раньше времени. Поэтому, для представления тела запроса и ответа используются потоки. Если вы не слышали или не использовали потоки в PHP – самое время с ними познакомиться!
Это была теория, перейдём к практике.
- Одним из первых в реализации этих интерфейсов подсуетился всё тот же Мэтью с компонентом zend-diactoros (часть Zend Framework)
- Команда Symfony также объявила о начале работ над адаптацией PSR-7
- Guzzle (самый продвинутый http клиент на PHP) планирует использовать PSR-7 и пилит свой вариант
- Aura Router версии 3.х (из фреймворка Aura) уже поддерживает PSR-7
- Помимо этого, Paul M. Jones (разработчик Aura) опубликовал в начале мая экспериментальный фреймворк Radar, который тоже использует PSR-7 (https://github.com/radarphp/Radar.Project). Посмотрите, заодно, на сам фреймворк – в нём есть свежие идеи, в частности Action-Domain-Responder паттерн – изысканный вариант MVC для веба, как написано у него на сайте
- Когда я искал реализации PSR-7 на GitHub, наткнулся на одну эзотерическую библиотеку icicle – библиотека для написания асинхронного кода, используя синхронные технологии PHP. Корутины и промисы, построенные поверх генераторов (ключевое слово yield в PHP 5.5)
- Ну а для любителей традиционных ценностей и фей, автор фреймворка PHPixie написал статью на Хабре о современном подходе к HTTP с PHPixie и PSR-7
И это далеко не полный список уже готовых или планируемых реализаций.
Как видим, астрологи объявили неделю PSR-7 и популяция фреймворков с его поддержкой удвоилась!
На сегодня всё, надеюсь выпуск был интересен и познавателен.
Если вы ещё не подписаны на подкаст – сделайте это прямо сейчас!
А затем приступайте к собственной реализации PSR-7. Ведь, как известно, каждый PHP разработчик должен хоть раз написать свой PSR-7 совместимый фреймворк! Собственный фреймворк у вас уже наверняка есть, осталось добавить туда поддержку PSR-7.
Slim Framework 3 планируется сделать по стандарту PSR-7.