您的 Slim 应用程序的路由和中间件会出现一个 PSR-7 请求对象,该对象表示您的 Web 服务器收到的当前 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 应用程序中间件中,如下所示
向应用中间件注入 PSR-7 请求
<?php
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 (Request $request, RequestHandler $handler) {
return $handler->handle($request);
});
// ...define app routes...
$app->run();
每个 HTTP 请求都有一个方法,通常是一个方法
您可以使用正确命名的 Request 对象方法 getMethod()
检查 HTTP 请求的方法。
$method = $request->getMethod();
可以伪造或覆盖 HTTP 请求方法。举例而言,如果您需要模仿仅支持 GET
或 POST
请求的传统网络浏览器使用 PUT
请求时,这会非常有用。
注意:要启用请求方法覆盖,必须将 Method Overriding Middleware 注入您的应用程序。
有两种方法可以覆盖 HTTP 请求方法。您可以在 POST
请求的主体中包含一个 METHOD
参数。HTTP 请求必须使用 application/x-www-form-urlencoded
内容类型。
使用 _METHOD 参数覆盖 HTTP 方法
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
HTTP 请求头覆盖 HTTP 请求方法。这适用于任何 HTTP 请求内容类型。
POST /path HTTP/1.1
Host: example.com
Content-type: application/json
Content-length: 16
X-Http-Method-Override: PUT
{"data":"value"}
若要请求与传入请求环境相关的数据,您需要使用 getServerParams()
。举例而言,若要获取单个服务器参数
$params = $request->getServerParams();
$authorization = $params['HTTP_AUTHORIZATION'] ?? null;
如果请求方法为 POST
且 Content-Type
为 application/x-www-form-urlencoded
或 multipart/form-data
,您可以如下方式检索所有 POST
参数
// Get all POST parameters
$params = (array)$request->getParsedBody();
// Get a single POST parameter
$foo = $params['foo'];
每个 HTTP 请求都有一个 URI,用于识别所请求的应用程序资源。HTTP 请求 URI 具有若干部分
http
或 https
)example.com
)80
或 443
)/users/1
)sort=created&dir=asc
)您可以使用 getUri()
方法请求 PSR-7 请求对象的 URI 对象
$uri = $request->getUri();
PSR-7 请求对象的 URI 本身就是一个对象,提供以下方法来检查 HTTP 请求的 URL 部分
a=1&b=2
)您可以使用 getQueryParams()
在请求对象上以关联数组的形式获取查询参数。
getQueryParams()
方法以关联数组的形式从 HTTP 请求的 URI 中检索所有查询参数。
如果没有查询参数,它会返回一个空数组。
在内部,此方法使用 parse_str 将查询字符串解析为数组。
用法
// URL: https://example.com/search?key1=value1&key2=value2
$queryParams = $request->getQueryParams();
Array
(
[key1] => value1
[key2] => value2
)
要从查询参数数组中读取单个值,可以使用参数的名称作为键。
// Output: value1
$key1 = $queryParams['key1'] ?? null;
// Output: value2
$key2 = $queryParams['key2'] ?? null;
// Output: null
$key3 = $queryParams['key3'] ?? null;
注意: ?? null
确保如果查询参数不存在,将返回 null
,而不是引发警告。
每个 HTTP 请求都有头信息。这些是描述 HTTP 请求的元数据,但在请求正文中不可见。Slim 的 PSR-7 请求对象提供了很多方法来检查其头信息。
可以使用 PSR-7 请求对象的 getHeaders()
方法以关联数组形式获取所有 HTTP 请求头信息。结果关联数组的键是头信息名称,而它的值本身是其各自头信息名称的字符串值的数字数组。
可以使用 PSR-7 请求对象的 getHeader($name)
方法获取单个头信息的值。这会返回给定头信息名称的值数组。请记住,一个 HTTP 头信息可以有多个值!
获取指定 HTTP 头信息的值
$headerValueArray = $request->getHeader('Accept');
还可以使用 PSR-7 请求对象的 getHeaderLine($name)
方法获取用逗号分隔的字符串,其中包含给定头信息的所有值。与 getHeader($name)
方法不同,此方法返回用逗号分隔的字符串。
将单个头信息的值获取为用逗号分隔的字符串
$headerValueString = $request->getHeaderLine('Accept');
可以使用 PSR-7 请求对象的 hasHeader($name)
方法测试头信息是否存在。
if ($request->hasHeader('Accept')) {
// Do something
}
可以使用请求的 getHeaderLine()
方法,通过检查头信息 X-Requested-With
是否为 XMLHttpRequest
,来检测 XHR 请求。
XHR 请求示例
POST /path HTTP/1.1
Host: example.com
Content-type: application/x-www-form-urlencoded
Content-length: 7
X-Requested-With: XMLHttpRequest
foo=bar
if ($request->getHeaderLine('X-Requested-With') === 'XMLHttpRequest') {
// Do something
}
可以使用请求对象的 getHeaderLine()
方法获取 HTTP 请求内容类型。
$contentType = $request->getHeaderLine('Content-Type');
可以使用请求对象的 getHeaderLine()
方法获取 HTTP 请求内容长度。
$length = $request->getHeaderLine('Content-Length');
每个 HTTP 请求都有正文。如果你正在构建一个使用 JSON 或 XML 数据的 Slim 应用程序,可以使用 PSR-7 请求对象的 getParsedBody()
方法将 HTTP 请求正文解析为原生 PHP 格式。请注意,正文解析因 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);
}
}
将 HTTP 请求正文解析为原生 PHP 格式
$parsedBody = $request->getParsedBody();
从技术上讲,PSR-7 Request 对象以 Psr\Http\Message\StreamInterface
的实例表示 HTTP 请求正文。您可以使用 PSR-7 Request 对象的 getBody()
方法获取 HTTP 请求正文 StreamInterface
实例。如果传入的 HTTP 请求大小未知或太大,以至于可用内存无法容纳,则此 getBody()
方法更可取。
获取 HTTP 请求正文
$body = $request->getBody();
生成的 Psr\Http\Message\StreamInterface
实例提供了以下方法来读取和迭代其底层的 PHP resource
。
$_FILES
中的文件上传可从 Request 对象的 getUploadedFiles()
方法使用。此方法返回一个数组,其键是 input
元素的名称。
获取上传的文件
$files = $request->getUploadedFiles();
$files
数组中的每个对象都是 Psr\Http\Message\UploadedFileInterface
的一个实例,并支持以下方法
请参阅 手册,了解如何使用 POST 表单上传文件。
使用 PSR-7 可以将对象/值注入请求对象以进一步进行处理。在您的应用程序中,中间件通常需要将信息传递给路由闭包,而实现此目的的方法是通过属性将其添加到请求对象。
示例,在请求对象上设置值。
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
$app->add(function (Request $request, RequestHandler $handler) {
// Add the session storage to your request as [READ-ONLY]
$request = $request->withAttribute('session', $_SESSION);
return $handler->handle($request);
});
示例,如何检索值。
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
$app->get('/test', function (Request $request, Response $response) {
// Get the session from the request
$session = $request->getAttribute('session');
$response->getBody()->write('Yay, ' . $session['name']);
return $response;
});
请求对象还具有批量功能。 $request->getAttributes()
和 $request->withAttributes()