Маршруты и промежуточное ПО вашего приложения Slim получают объект запроса PSR-7, который представляет текущий HTTP-запрос, полученный вашим веб-сервером. Объект запроса реализует PSR-7 ServerRequestInterface, с помощью которого вы можете проверять и обрабатывать метод HTTP-запроса, заголовки и тело.
Объект запроса PSR-7 внедряется в маршруты вашего приложения Slim в качестве первого аргумента обработчика, например:
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
$app->get('/hello', function (Request $request, Response $response) {
$response->getBody()->write('Hello World');
return $response;
});
$app->run();Объект запроса PSR-7 внедряется в промежуточное ПО вашего приложения Slim в качестве первого аргумента обработчика промежуточного ПО, например:
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
$app->add(function (ServerRequestInterface $request, RequestHandler $handler) {
return $handler->handle($request);
});
// ...определение маршрутов приложения...
$app->run();Каждый HTTP-запрос включает метод. Обычно, один из:
Вы можете проверить метод HTTP-запроса с помощью метода getMethod() объекта запроса.
$method = $request->getMethod();Можно подделать или переопределить метод HTTP-запроса. Это полезно, если, например, вам нужно имитировать запрос PUT, используя традиционный веб-браузер, который поддерживает только запросы GET или POST.
Есть два способа переопределить метод HTTP-запроса.
Вы можете включить параметр _METHOD в тело запроса POST. HTTP-запрос должен использовать тип содержимого application/x-www-form-urlencoded.
POST /path HTTP/1.1
Host: example.com
Content-type: application/x-www-form-urlencoded
Content-length: 22
data=value&_METHOD=PUTТак же вы можете переопределить метод запроса, передав нужный метод в заголовке запроса X-Http-Method-Override. Это сработает с любым типом содержимого запроса.
POST /path HTTP/1.1
Host: example.com
Content-type: application/json
Content-length: 16
X-Http-Method-Override: PUT
{"data":"value"}Каждый HTTP-запрос имеет URI, который идентифицирует запрошенный ресурс приложения. URI HTTP-запроса состоит из нескольких частей:
http or https)example.com)80 or 443)/users/1)sort=created&dir=asc)Вы можете извлечь объект URI object с помощью метода getUri() объекта запроса:
$uri = $request->getUri();объект URI запроса предоставляет следующие методы для проверки частей URL-адреса HTTP-запроса:
a=1&b=2)Вы можете получить ассоциативный массив параметров запроса с помощью метода getQueryParams() объекта запроса.
getBasePath() объекта Uri.
Если приложение Slim установлено в корне домена, данный метод вернет пустую строку.
Каждый HTTP-запрос имеет заголовки. Это метаданные, которые описывают HTTP-запрос, но не видны в теле запроса. Объект запроса Slim PSR-7 предоставляет несколько методов для проверки его заголовков.
Вы можете извлечь все заголовки HTTP-запроса в виде ассоциативного массива с помощью метода getHeaders() объекта запроса PSR-7.
Ключи результирующего ассоциативного массива являются именами заголовков, а его значения сами являются массивом строковых значений для соответствующего имени заголовка.
$headers = $request->getHeaders();
foreach ($headers as $name => $values) {
echo $name . ": " . implode(", ", $values);
}Вы можете получить значения одного заголовка с помощью метода getHeader($name) объекта запроса PSR-7.
Метод возвращает массив значений для данного имени заголовка.
Помните, что один заголовок HTTP может иметь более одного значения!
$headerValueArray = $request->getHeader('Accept');Вы также можете получить разделенную запятыми строку со всеми значениями для данного заголовка с помощью метода getHeaderLine($name) объекта запроса PSR-7. В отличие от метода getHeader($name), этот метод возвращает строку объединенных через запятую значений.
$headerValueString = $request->getHeaderLine('Accept');Вы можете проверить наличие заголовка с помощью метода hasHeader($name) объекта запроса PSR-7.
if ($request->hasHeader('Accept')) {
// Do something
}Каждый HTTP-запрос имеет тело. Если вы создаете приложение Slim, которое использует данные JSON или XML,
вы можете использовать метод getParsedBody() объекта запроса PSR-7 для получения десериализованного тела запроса.
Обратите внимание, что синтаксический анализ тела может отличаться в разных реализациях PSR-7.
Возможно, вам потребуется реализовать промежуточное ПО для анализа тела запроса в зависимости от выбранной вами реализации PSR-7.
Вот пример для десериализации тела запроса в формате JSON:
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
class JsonBodyParserMiddleware implements MiddlewareInterface
{
public function process(Request $request, RequestHandler $handler): Response
{
$contentType = $request->getHeaderLine('Content-Type');
if (strstr($contentType, 'application/json')) {
$contents = json_decode(file_get_contents('php://input'), true);
if (json_last_error() === JSON_ERROR_NONE) {
$request = $request->withParsedBody($contents);
}
}
return $handler->handle($request);
}
}$parsedBody = $request->getParsedBody();Технически, объект запроса PSR-7 представляет тело HTTP-запроса как экземпляр Psr\Http\Message\StreamInterface.
Вы можете получить экземпляр HTTP-запроса StreamInterface с помощью метода getBody() объекта запроса PSR-7.
Метод getBody() предпочтителен, если размер входящего HTTP-запроса неизвестен или слишком велик для доступной памяти.
$body = $request->getBody();Результирующий экземпляр Psr\Http\Message\StreamInterface предоставляет следующие методы для чтения и итерации своего базового PHP-ресурса:
Список загруженных файлы в $ _FILES доступен из метода getUploadedFiles() объекта Request. Метод возвращает массив с ключом по имени элемента input.
$files = $request->getUploadedFiles();Каждый элемент массива $files является экземпляром Psr\Http\Message\UploadedFileInterface и поддерживает методы:
См в книге рецептов, как загружать файлы с помощью POST-формы.
Реализация запроса Slim в PSR-7 предоставляет дополнительные методы, которые помогут вам работать с HTTP-запросом.
Вы можете определить XHR-запрос, проверив значение XMLHttpRequest в заголовке X-Requested-With.
POST /path HTTP/1.1
Host: example.com
Content-type: application/x-www-form-urlencoded
Content-length: 7
X-Requested-With: XMLHttpRequest
foo=barif ($request->getHeaderLine('X-Requested-With') === 'XMLHttpRequest') {
// Do something
}Вы можете узнать тип содержимого запроса с помощью метода getHeaderLine() объекта запроса.
$contentType = $request->getHeaderLine('Content-Type');Вы можете узнать размер содержимого запроса с помощью метода getHeaderLine() объекта запроса.
$length = $request->getHeaderLine('Content-Length');Получить значение одного параметра можно с помощью метода getServerParams()
$params = $request->getServerParams();
$authorization = isset($params['HTTP_AUTHORIZATION']) ? $params['HTTP_AUTHORIZATION'] : null;Иногда в промежуточном ПО требуется параметр вашего маршрута.
В этом примере мы сначала проверяем, что пользователь вошел в систему, а затем, что у пользователя есть разрешения на просмотр конкретного видео, которое он пытается просмотреть.
<?php
$app
->get('/course/{id}', Video::class.":watch")
->add(PermissionMiddleware::class);<?php
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Routing\RouteContext;
class PermissionMiddleware {
public function __invoke(Request $request, RequestHandler $handler) {
$routeContext = RouteContext::fromRequest($request);
$route = $routeContext->getRoute();
$courseId = $route->getArgument('id');
// ...логика проверки доступа...
return $handler->handle($request);
}
}Чтобы получить базовый путь в обработчике маршрута, просто сделайте следующее:
<?php
use Slim\Factory\AppFactory;
use Slim\Routing\RouteContext;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
$app->get('/', function($request, $response) {
$routeContext = RouteContext::fromRequest($request);
$basePath = $routeContext->getBasePath();
// ...
return $response;
});С PSR-7 возможно ввести объекты-значения в объект запроса для дальнейшей обработки. В ваших приложениях промежуточному ПО часто требуется передавать какую-то информацию обработчику маршрута, и хорошим способом сделать это является добавление этой информации в атрибутах запроса.
$app->add(function ($request, $handler) {
// добавление хранилища сессии в запрос
$request = $request->withAttribute('session', $_SESSION);
return $handler->handle($request);
});$app->get('/test', function ($request, $response, $args) {
$session = $request->getAttribute('session'); // получение хранилища сессии из запроса
return $response->write('Yay, ' . $session['name']);
});