レスポンス

Slimアプリケーションのルートとミドルウェアには、クライアントに返される現在のHTTPレスポンスを表すPSR-7レスポンスオブジェクトが提供されます。レスポンスオブジェクトは、PSR-7 ResponseInterface を実装しており、HTTPレスポンスのステータス、ヘッダー、およびボディを検査および操作できます。

レスポンスオブジェクトを取得する方法

PSR-7レスポンスオブジェクトは、次のようにルートコールバックの2番目の引数として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();
図1:PSR-7レスポンスをアプリケーションルートコールバックに挿入します。

レスポンスステータス

すべてのHTTPレスポンスには、数値のステータスコードがあります。ステータスコードは、クライアントに返されるHTTPレスポンスの*種類*を識別します。PSR-7レスポンスオブジェクトのデフォルトのステータスコードは 200(OK)です。 getStatusCode()メソッドを使用して、PSR-7レスポンスオブジェクトのステータスコードを取得できます。

$status = $response->getStatusCode();
図3:レスポンスステータスコードを取得します。

PSR-7レスポンスオブジェクトをコピーし、新しいステータスコードを割り当てることができます。

$newResponse = $response->withStatus(302);
図4:新しいステータスコードでレスポンスを作成します。

レスポンスヘッダー

すべてのHTTPレスポンスにはヘッダーがあります。これらは、HTTPレスポンスを記述するメタデータですが、レスポンスのボディには表示されません。PSR-7レスポンスオブジェクトは、ヘッダーを検査および操作するためのいくつかのメソッドを提供します。

すべてのヘッダーを取得する

PSR-7レスポンスオブジェクトの getHeaders()メソッドを使用して、すべてのHTTPレスポンスヘッダーを連想配列としてフェッチできます。結果の連想配列のキーはヘッダー名であり、その値は、それぞれのヘッダー名の文字列値の数値配列です。

$headers = $response->getHeaders();
foreach ($headers as $name => $values) {
    echo $name . ": " . implode(", ", $values);
}
図5:すべてのHTTPレスポンスヘッダーを連想配列としてフェッチして反復処理します。

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

PSR-7レスポンスオブジェクトの getHeader($name)メソッドを使用して、単一のヘッダーの値を取得できます。これは、指定されたヘッダー名の値の配列を返します。*単一のHTTPヘッダーに複数の値が含まれている場合がある*ことに注意してください。

$headerValueArray = $response->getHeader('Vary');
図6:特定のHTTPヘッダーの値を取得します。

また、PSR-7レスポンスオブジェクトの getHeaderLine($name)メソッドを使用して、指定されたヘッダーのすべての値を含むカンマ区切りの文字列をフェッチすることもできます。 getHeader($name)メソッドとは異なり、このメソッドはカンマ区切りの文字列を返します。

$headerValueString = $response->getHeaderLine('Vary');
図7:単一ヘッダーの値をカンマ区切りの文字列として取得します。

ヘッダーを検出する

PSR-7レスポンスオブジェクトの hasHeader($name)メソッドを使用して、ヘッダーの存在をテストできます。

if ($response->hasHeader('Vary')) {
    // Do something
}
図8:特定のHTTPヘッダーの存在を検出します。

ヘッダーを設定する

PSR-7レスポンスオブジェクトの withHeader($name, $value)メソッドを使用して、ヘッダー値を設定できます。

$newResponse = $oldResponse->withHeader('Content-type', 'application/json');
図9:HTTPヘッダーを設定する
注意
レスポンスオブジェクトは不変です。このメソッドは、新しいヘッダー値を持つレスポンスオブジェクトの*コピー*を返します。 **このメソッドは破壊的**であり、同じヘッダー名に既に関連付けられている既存のヘッダー値を*置き換え*ます。

ヘッダーを追加する

PSR-7レスポンスオブジェクトのwithAddedHeader($name, $value)メソッドを使用して、ヘッダー値を追加できます。

$newResponse = $oldResponse->withAddedHeader('Allow', 'PUT');
図10:HTTPヘッダーを追加する
注意
withHeader()メソッドとは異なり、このメソッドは新しい値を、同じヘッダー名に既に存在する値のセットに*追加*します。レスポンスオブジェクトは不変です。このメソッドは、追加されたヘッダー値を持つレスポンスオブジェクトの*コピー*を返します。

ヘッダーを削除する

レスポンスオブジェクトのwithoutHeader($name)メソッドを使用して、ヘッダーを削除できます。

$newResponse = $oldResponse->withoutHeader('Allow');
図11:HTTPヘッダーを削除する
注意
レスポンスオブジェクトは不変です。このメソッドは、指定されたヘッダーのないレスポンスオブジェクトの*コピー*を返します。

レスポンスボディ

HTTPレスポンスには通常、ボディがあります。

PSR-7リクエストオブジェクトと同様に、PSR-7レスポンスオブジェクトはボディをPsr\Http\Message\StreamInterfaceのインスタンスとして実装します。PSR-7レスポンスオブジェクトのgetBody()メソッドを使用して、HTTPレスポンスボディのStreamInterfaceインスタンスを取得できます。送信HTTPレスポンスの長さが不明な場合、または使用可能なメモリに対して大きすぎる場合は、getBody()メソッドが推奨されます。

$body = $response->getBody();
図12:HTTPレスポンスボディを取得する

結果のPsr\Http\Message\StreamInterfaceインスタンスは、基になるPHP resourceから読み取り、反復処理し、書き込むための以下のメソッドを提供します.

  • getSize()
  • tell()
  • eof()
  • isSeekable()
  • seek()
  • rewind()
  • isWritable()
  • write($string)
  • isReadable()
  • read($length)
  • getContents()
  • getMetadata($key = null)

ほとんどの場合、PSR-7レスポンスオブジェクトに書き込む必要があります。write()メソッドを使用して、StreamInterfaceインスタンスにコンテンツを書き込むことができます。

$body = $response->getBody();
$body->write('Hello');
図13:HTTPレスポンスボディにコンテンツを書き込む

また、PSR-7レスポンスオブジェクトのボディを完全に新しいStreamInterfaceインスタンスに*置き換える*こともできます。これは、リモートの宛先(例:ファイルシステムまたはリモートAPI)からのコンテンツをHTTPレスポンスにパイプしたい場合に特に役立ちます。 withBody(StreamInterface $body)メソッドを使用して、PSR-7レスポンスオブジェクトのボディを置き換えることができます。その引数は、**必ず** Psr\Http\Message\StreamInterfaceのインスタンスでなければなりません。

use GuzzleHttp\Psr7\LazyOpenStream;

$newStream = new LazyOpenStream('/path/to/file', 'r');
$newResponse = $oldResponse->withBody($newStream);
図14:HTTPレスポンスボディを置き換える
注意
レスポンスオブジェクトは不変です。このメソッドは、新しいボディを含むレスポンスオブジェクトの*コピー*を返します。

JSONを返す

最も単純な形式では、JSONデータはデフォルトの200 HTTPステータスコードで返すことができます。

$data = array('name' => 'Bob', 'age' => 40);
$payload = json_encode($data);

$response->getBody()->write($payload);
return $response
          ->withHeader('Content-Type', 'application/json');
図15:200 HTTPステータスコードでJSONを返す。

カスタムHTTPステータスコードでJSONデータを返すこともできます。

$data = array('name' => 'Rob', 'age' => 40);
$payload = json_encode($data);

$response->getBody()->write($payload);
return $response
          ->withHeader('Content-Type', 'application/json')
          ->withStatus(201);
図16:201 HTTPステータスコードでJSONを返す。
注意
レスポンスオブジェクトは不変です。このメソッドは、新しいContent-Typeヘッダーを持つレスポンスオブジェクトの*コピー*を返します。 **このメソッドは破壊的**であり、既存のContent-Typeヘッダーを*置き換え*ます。

リダイレクトを返す

Locationヘッダーを使用して、HTTPクライアントをリダイレクトできます。

return $response
  ->withHeader('Location', 'https://www.example.com')
  ->withStatus(302);
図17:https://www.example.comへのリダイレクトを返す