リクエスト

Slim アプリのルートとミドルウェアには、Webサーバーが受信した現在の HTTP リクエストを表す PSR-7 リクエストオブジェクトが提供されます。リクエストオブジェクトは、HTTP リクエストメソッド、ヘッダー、およびボディを検査および操作できる PSR-7 ServerRequestInterface を実装します。

リクエストオブジェクトを取得する方法

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 メソッド

すべての HTTP リクエストには、通常は次のいずれかのメソッドがあります

  • GET
  • POST
  • PUT
  • DELETE
  • HEAD
  • PATCH
  • OPTIONS

HTTP リクエストのメソッドは、getMethod() という名前のリクエストオブジェクトメソッドを使用して検査できます。

$method = $request->getMethod();

HTTP リクエストメソッドを偽装または*オーバーライド*することができます。これは、たとえば、GET または POST リクエストのみをサポートする従来の Web ブラウザを使用して PUT リクエストを模倣する必要がある場合に役立ちます。

**注:** リクエストメソッドのオーバーライドを有効にするには、メソッドオーバーライドミドルウェアをアプリケーションに挿入する必要があります。

HTTP リクエストメソッドをオーバーライドするには、2 つの方法があります。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 パラメータ

リクエストメソッドが POST で、Content-Typeapplication/x-www-form-urlencoded または multipart/form-data のいずれかである場合、次のようにすべての POST パラメータを取得できます

// Get all POST parameters
$params = (array)$request->getParsedBody();

// Get a single POST parameter
$foo = $params['foo'];

リクエスト URI

すべての HTTP リクエストには、リクエストされたアプリケーションリソースを識別する URI があります。HTTP リクエスト URI には、いくつかの部分があります

  • スキーム (例: http または https)
  • ホスト (例: example.com)
  • ポート (例: 80 または 443)
  • パス (例: /users/1)
  • クエリ文字列 (例: sort=created&dir=asc)

PSR-7 リクエストオブジェクトの URI オブジェクト は、getUri() メソッドを使用して取得できます

$uri = $request->getUri();

PSR-7 リクエストオブジェクトの URI は、HTTP リクエストの URL 部分を検査するための以下のメソッドを提供するオブジェクトです

  • getScheme()
  • getAuthority()
  • getUserInfo()
  • getHost()
  • getPort()
  • getPath()
  • getQuery() (完全なクエリ文字列を返します。例: a=1&b=2)
  • getFragment()

リクエストオブジェクトで 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 リクエストヘッダーを連想配列として取得できます。結果の連想配列のキーはヘッダー名であり、その値はそれぞれのヘッダー名の文字列値の数値配列です。

$headers = $request->getHeaders();
foreach ($headers as $name => $values) {
    echo $name . ": " . implode(", ", $values);
}
図 5: すべての HTTP リクエストヘッダーを連想配列として取得して反復処理します。

1 つのヘッダーを取得する

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
}

XHR リクエストの検出

リクエストの getHeaderLine() メソッドを使用して、ヘッダー X-Requested-WithXMLHttpRequest であるかどうかを確認することで、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 リクエストオブジェクトは HTTP リクエストボディを Psr\Http\Message\StreamInterface のインスタンスとして表します。PSR-7 リクエストオブジェクトの getBody() メソッドを使用して、HTTP リクエストボディの StreamInterface インスタンスを取得できます。受信 HTTP リクエストのサイズが不明な場合、または使用可能なメモリに対して大きすぎる場合は、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 内のファイルアップロードは、リクエストオブジェクトの getUploadedFiles() メソッドから入手できます。これは、input 要素の名前をキーとする配列を返します。

アップロードされたファイルを取得する

$files = $request->getUploadedFiles();

$files 配列内の各オブジェクトは Psr\Http\Message\UploadedFileInterface のインスタンスであり、以下のメソッドをサポートしています

  • getStream()
  • moveTo($targetPath)
  • getSize()
  • getError()
  • getClientFilename()
  • getClientMediaType()

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()