====== Slim4 リクエスト ====== Version 4.5.0 --- //[[http://www.y2sunlight.com|y2sunlight]] 2020-09-23// [[slim:top|Slim に戻る]] 関連記事 * [[slim:4:install|Slim4 インストール]] * [[slim:4:concepts|Slim4 コンセプト]] * Slim4 リクエスト * [[slim:4:response|Slim4 レスポンス]] * [[slim:4:routing|Slim4 ルーティング]] * [[slim:4:middleware|Slim4 ミドルウェア]] * [[slim:4:cookbook|Slim4 クックブック]] 本章は以下のサイトの **The Request** のセクションを翻訳し若干の補足を加えたのもです。 * https://www.slimframework.com/docs/v4/ ----- Slimアプリのルート(route)とミドルウェアには、ウェブサーバーが受信した現在のHTTPリクエストを表すPSR-7リクエストオブジェクトが与えられます。リクエストオブジェクトは、HTTPリクエストメソッド、ヘッダー、およびボディを検査および操作できる [[https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface|PSR-7 ServerRequestInterface]] を実装しています。 ===== Requestオブジェクトを取得する方法 ===== PSR-7リクエストオブジェクトは、次のようにルート(route)コールバックの最初の引数としてSlimアプリケーションルート(route)に注入されます。 get('/hello', function (Request $request, Response $response) { $response->getBody()->write('Hello World'); return $response; }); $app->run(); PSR-7リクエストオブジェクトは、次のように呼び出し可能なミドルウェアの最初の引数としてSlimアプリケーションミドルウェアに注入されます。 add(function (Request $request, RequestHandler $handler) { return $handler->handle($request); }); // ...define app routes... $app->run(); \\ ===== リクエストメソッド ===== すべてのHTTPリクエストには、通常、次のいずれかのメソッドがあります: * GET * POST * PUT * DELETE * HEAD * PATCH * OPTIONS ''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"} \\ ===== リクエストURI ===== すべてのHTTPリクエストには、リクエストされたアプリケーションリソースを識別するURIがあります。HTTPリクエストURIにはいくつかの部分があります。 * Scheme (例えば: ''http'' or ''https'') * Host (例えば: ''example.com'') * Port (例えば: ''80'' or ''443'') * Path (例えば: ''/users/1'') * Query string (例えば: ''sort=created&dir=asc'') PSR-7リクエストオブジェクトの [[https://www.php-fig.org/psr/psr-7/#35-psrhttpmessageuriinterface|URIオブジェクト]] は、その ''getUri()'' メソッドを使用してフェッチできます。 $uri = $request->getUri(); PSR-7リクエストオブジェクトのURIは、それ自体がHTTPリクエストのURL部分を検査するための次のメソッドを提供するオブジェクトです: * getScheme() * getAuthority() * getUserInfo() * getHost() * getPort() * getPath() * getBasePath() * getQuery() (完全なクエリ文字列を返します、例えば:''a=1&b=2'') * getFragment() * getBaseUrl() ''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'' 入力を解析する例を示します。 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'' を読み取って反復するための次のメソッドを提供します。 * getSize() * tell() * eof() * isSeekable() * seek() * rewind() * isWritable() * write($string) * isReadable() * read($length) * getContents() * getMetadata($key = null) \\ ===== アップロードファイル ===== ''$_FILES'' でのファイルのアップロードは、Requestオブジェクトの ''getUploadedFiles()'' メソッドから利用できます。これは、''input'' 要素の名前でキー設定された配列を返します。 $files = $request->getUploadedFiles(); ''$files'' 配列内の各オブジェクトは、''Psr\Http\Message\UploadedFileInterface'' のインスタンスであり、次のメソッドをサポートします。 * getStream() * moveTo($targetPath) * getSize() * getError() * getClientFilename() * getClientMediaType() POSTフォームを使用してファイルをアップロードする方法については、[[https://www.slimframework.com/docs/v4/cookbook/uploading-files.html|cookbook]] を参照してください。 \\ ===== リクエストヘルパー ===== SlimのPSR-7リクエストの実装は、以下の追加の独自メソッドを提供し、HTTPリクエストをさらに検査するのを助けます。 ==== XHRリクエストの検出 ==== リクエストの ''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); getRoute(); $courseId = $route->getArgument('id'); // do permission logic... return $handler->handle($request); } } \\ ===== ルート内からベースパスを取得する ===== ルート内からベースパスを取得するには、次の手順を実行します: 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()'' と同じような一括関数もあります。 \\