Version 4.5.0
— y2sunlight 2020-09-23
関連記事
本章は以下のサイトの The Request のセクションを翻訳し若干の補足を加えたのもです。
Slimアプリのルート(route)とミドルウェアには、ウェブサーバーが受信した現在のHTTPリクエストを表すPSR-7リクエストオブジェクトが与えられます。リクエストオブジェクトは、HTTPリクエストメソッド、ヘッダー、およびボディを検査および操作できる PSR-7 ServerRequestInterface を実装しています。
PSR-7リクエストオブジェクトは、次のようにルート(route)コールバックの最初の引数としてSlimアプリケーションルート(route)に注入されます。
<?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\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リクエストには、通常、次のいずれかのメソッドがあります:
getMethod()
という適切な名前の Request オブジェクトメソッドを使用して、HTTPリクエストのメソッドを検査できます。
$method = $request->getMethod();
HTTPリクエストメソッドを偽装またはオーバーライドすることが可能です。これは、たとえば、GET
または POST
リクエストのみをサポートする従来のWebブラウザを使用して PUT
リクエストを模倣する必要がある場合に役立ちます。
注意!
リクエストメソッドのオーバーライドを有効にするには、メソッドオーバーライド・ミドルウェアをアプリケーションに注入する必要があります。
HTTPリクエストメソッドをオーバーライドする方法は2つあります。POST
リクエストのボディに METHOD
パラメータを含めることができます。この時、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
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"}
すべてのHTTPリクエストには、リクエストされたアプリケーションリソースを識別するURIがあります。HTTPリクエストURIにはいくつかの部分があります。
http
or https
)example.com
)80
or 443
)/users/1
)sort=created&dir=asc
)
PSR-7リクエストオブジェクトの URIオブジェクト は、その getUri()
メソッドを使用してフェッチできます。
$uri = $request->getUri();
PSR-7リクエストオブジェクトのURIは、それ自体がHTTPリクエストのURL部分を検査するための次のメソッドを提供するオブジェクトです:
a=1&b=2
)
getQueryParams()
を使用して、Requestオブジェクトの連想配列としてクエリパラメーターを取得できます。
ペースパス
Slimアプリケーションのフロントコントローラーがドキュメントルートディレクトリ下の物理サブディレクトリにある場合は、UriオブジェクトのgetBasePath()
メソッドを使用してHTTPリクエストの(ドキュメントルートを基準とした)物理ベースパスをフェッチできます。Slimアプリケーションがドキュメントルートの最上位ディレクトリにインストールされている場合、これは空の文字列になります。
HTTPリクエストにはヘッダーがあります。これらはHTTPリクエストを説明するメタデータですが、リクエストの本文には現れません。Slimの PSR-7 リクエストオブジェクトは、ヘッダーを検査するためのいくつかのメソッドを提供します。
PSR-7リクエストオブジェクトの getHeaders()
メソッドを使用して、すべてのHTTPリクエストヘッダーを連想配列としてフェッチできます。結果として得られる連想配列のキーはヘッダー名であり、その値自体がそれぞれのヘッダー名に対する文字列値の数値配列です。
$headers = $request->getHeaders(); foreach ($headers as $name => $values) { echo $name . ": " . implode(", ", $values); }
PSR-7リクエストオブジェクトの getHeader($name)
メソッドを使用して、単一のヘッダーの値を取得できます。これにより、指定されたヘッダー名に対する値の配列が返されます。1つの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 }
すべての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); } }
$parsedBody = $request->getParsedBody();
技術的に言えば、PSR-7リクエストオブジェクトは、HTTPリクエストボディを Psr\Http\Message\StreamInterface
のインスタンスとして表現しています。PSR-7リクエストオブジェクトの getBody()
メソッドを使用して、HTTPリクエストボディの StreamInterface
インスタンスを取得できます。getBody()
メソッドは、着信HTTPリクエストのサイズが不明であるか、使用可能なメモリに対して大きすぎる場合に適しています。
$body = $request->getBody();
結果として得られる Psr\Http\Message\StreamInterface
インスタンスは、基礎となるPHPの resource
を読み取って反復するための次のメソッドを提供します。
$_FILES
でのファイルのアップロードは、Requestオブジェクトの getUploadedFiles()
メソッドから利用できます。これは、input
要素の名前でキー設定された配列を返します。
$files = $request->getUploadedFiles();
$files
配列内の各オブジェクトは、Psr\Http\Message\UploadedFileInterface
のインスタンスであり、次のメソッドをサポートします。
POSTフォームを使用してファイルをアップロードする方法については、cookbook を参照してください。
SlimのPSR-7リクエストの実装は、以下の追加の独自メソッドを提供し、HTTPリクエストをさらに検査するのを助けます。
リクエストの getHeaderLine()
メソッドを使用して、ヘッダー X-Requested-With
が XMLHttpRequest
であるかどうかを確認することで、XHRリクエストを検出できます。
XHRとはXMLHttpRequestの略で、JavaScriptなどのからサーバとHTTP通信を行うためのAjaxで使われる組み込みオブジェクトの事です。
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 }
Requestオブジェクトの getHeaderLine()
メソッドを使用してHTTPリクエストコンテンツタイプをフェッチできます。
$contentType = $request->getHeaderLine('Content-Type');
Requestオブジェクトの getHeaderLine()
メソッドを使用して、HTTPリクエストのコンテンツの長さをフェッチできます。
$length = $request->getHeaderLine('Content-Length');
着信リクエストの環境に関連するデータをフェッチするには、getServerParams()
を使用する必要があります。
例えば、単一のサーバーパラメータを取得するには:
$params = $request->getServerParams(); $authorization = $params['HTTP_AUTHORIZATION'] ?? null;
you can retrieve all POST
parameters as follows:
リクエストメソッドが 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'];
ミドルウェアでは、ルート(route)のパラメータが必要になる場合があります。
この例では、最初にユーザーがログインしていることを確認し、次にユーザーが表示しようとしている特定のビデオを表示する権限を持っていることを確認しています。
$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'); // do permission logic... return $handler->handle($request); } }
ルート内からベースパスを取得するには、次の手順を実行します:
<?php use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Slim\Factory\AppFactory; use Slim\Routing\RouteContext; require __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); $app->get('/', function(Request $request, Response $response) { $routeContext = RouteContext::fromRequest($request); $basePath = $routeContext->getBasePath(); // ... return $response; });
PSR-7を使用すると、さらに処理するために、オブジェクト/値をリクエストオブジェクトに注入することができます。アプリケーションでは、ミドルウェアは多くの場合、ルート(route)クロージャーに情報を渡す必要があります。そのための方法は、属性を介してリクエストオブジェクトに情報を追加することです。
例:リクエストオブジェクトに値を設定します。
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()
と同じような一括関数もあります。