Роутинг для PSR 7 Response/Request. Часть 1: Обзор
Сухая выжимка из видео Дмитрия Елисеева PSR-7 фреймворк 2/6: Контроллеры и маршрутизация.
Вводные данные
У нас уже есть входная точка для нашего приложения и подключена библиотека для работы с HTTP PSR 7 — в примерах будет Zend Diactoros.
В итоге наш index.php выглядит так:
<\?php
use Zend\Diactoros\Response\HtmlResponse;
use Zend\Diactoros\Response\SapiEmitter;
use Zend\Diactoros\ServerRequestFactory;
chdir(dirname(__DIR__));
require 'vendor/autoload.php';
### Initialization
$request = ServerRequestFactory::fromGlobals();
### Action
$name = $request->getQueryParams()['name'] ?? 'Guest';
$response = new HtmlResponse('Hello, ' . $name . '!');
### Postprocessing
$response = $response->withHeader('X-Developer', 'maksfedorov.ru');
### Sending
$emitter = new SapiEmitter();
$emitter->emit($response);
По коду:
- Подключаем фабрику Zend Diactoros, которая конвертирует глобальные переменные в объекты Request и Response
- Создаем объект Response и передаем в него значение GET параметра name или строку ’Guest’
- Добавляем свой пользовательский заголовок к объекту Response
- Отправляем на вывод, добавляя код ответа и тип контента
Первый роутинг
Получим наш пользовательский путь (после исполняющего скрипта, до параметров). На основе этого пути зададим свой объект Response и передадим в каждый соответствующий контент.
Помимо простых путей, мы можем добавить сюда более гибкие пути, например для блога в виде JSON:
<\?php
### Action
$path = $request->getUri()->getPath();
if ($path === '/') {
$name = $request->getQueryParams()['name'] ?? 'Guest';
$response = new HtmlResponse('Hello, ' . $name . '!');
} elseif ($path === '/about') {
$response = new HtmlResponse('I am a simple site');
} else {
$response = new HtmlResponse('Undefined page', 404);
}
# ...
и его отдельных статей, проверяя путь каждой статьи через регулярное выражение:
<\?php
Это и есть простейший роутинг, но как понимаете — если контент будет сколь заметным или путей будет много — работать с таким кодом будет крайне не удобно.
В самом конце мы разнесем по разным файлам, но пока мы будет делать это постепенно, шаг за шагом показывая, как это будет происходить.
Оптимизация
Чтобы в условиях для каждого роута наши переменные не зассоряли наш эфир и глобальные переменные — поместим этот код в анонимные функции, присвоим их результат переменной $action и после условия выведем результат подходящей условию переменной:
Но у нас появляются неудобства для адресов, которые мы проверяем через регулярку и у нас появляются произвольные параметры. Мы можем передать результат регулярки в качестве параметра в анонимную функцию, но мы не можем точно знать, какие переменные мы можем ожидать.
Но мы можем воспользоваться методом withAttribute() объекта Request, тем самым изменяя сам объект Request, который мы и передаем в анонимную функцию, в итоге выглядет это так:
<\?php
ADR (Action Domain Response)
Action Domain Response — частный и упрощенный случай MVC.
Суть этого подхода для нас — нам нужно сделать систему маршрутизации, при которой в зависимости от разных адресов мы возвращаем нужную анонимную функцию.
Простейший вариант:
<\?php
Но для учета HTTP методов (например для REST API) это будет иметь такой вид:
<\?php
Теперь мы получили представление о том, что нам нужно получить и как это должно работать, в следующей части разберем принцип построения системы маршрутизации перейти к созданию маршрутизации→