2 フォロワー

レスポンス

アプリケーションがリクエストの処理を完了すると、レスポンスオブジェクトを生成し、エンドユーザーに送信します。レスポンスオブジェクトには、HTTPステータスコード、HTTPヘッダー、ボディなどの情報が含まれています。Webアプリケーション開発の最終的な目標は、本質的に様々なリクエストに対してこのようなレスポンスオブジェクトを構築することです。

ほとんどの場合、デフォルトでyii\web\Responseのインスタンスである、response アプリケーションコンポーネントを主に扱う必要があります。しかし、Yiiでは独自のレスポンスオブジェクトを作成し、エンドユーザーに送信することもできます(後述)。

このセクションでは、エンドユーザーへのレスポンスの構成と送信方法について説明します。

ステータスコード

レスポンスを作成する際、最初にすべきことの1つは、リクエストが正常に処理されたかどうかを伝えることです。yii\web\Response::$statusCodeプロパティを設定することで行います。このプロパティには、有効なHTTPステータスコードのいずれかを指定できます。たとえば、リクエストが正常に処理されたことを示すには、ステータスコードを200に設定します。

Yii::$app->response->statusCode = 200;

ただし、ほとんどの場合、ステータスコードを明示的に設定する必要はありません。これは、yii\web\Response::$statusCodeのデフォルト値が200であるためです。リクエストが失敗したことを示したい場合は、次のように適切なHTTP例外をスローできます。

throw new \yii\web\NotFoundHttpException;

エラーハンドラーが例外をキャッチすると、例外からステータスコードを抽出し、レスポンスに割り当てます。上記のyii\web\NotFoundHttpExceptionは、HTTPステータス404に関連付けられています。Yiiには、以下のHTTP例外が事前に定義されています。

スローしたい例外が上記リストにない場合は、yii\web\HttpExceptionを拡張して作成するか、ステータスコードを指定して直接スローできます。

throw new \yii\web\HttpException(402);

HTTPヘッダー

responseコンポーネントのヘッダーコレクションを操作することで、HTTPヘッダーを送信できます。

$headers = Yii::$app->response->headers;

// add a Pragma header. Existing Pragma headers will NOT be overwritten.
$headers->add('Pragma', 'no-cache');

// set a Pragma header. Any existing Pragma headers will be discarded.
$headers->set('Pragma', 'no-cache');

// remove Pragma header(s) and return the removed Pragma header values in an array
$values = $headers->remove('Pragma');

情報:ヘッダー名は、大文字と小文字を区別しません。yii\web\Response::send()メソッドが呼び出されるまで、新しく登録されたヘッダーはユーザーに送信されません。

レスポンスボディ

ほとんどのレスポンスは、エンドユーザーに表示したいコンテンツを提供する本文を持つ必要があります。

既にフォーマット済みの本文文字列がある場合は、レスポンスのyii\web\Response::$contentプロパティに割り当てることができます。例:

Yii::$app->response->content = 'hello world!';

データがエンドユーザーに送信される前にフォーマットする必要がある場合は、formatプロパティとdataプロパティの両方を設定する必要があります。formatプロパティは、dataをどのフォーマットでフォーマットするかを指定します。例:

$response = Yii::$app->response;
$response->format = \yii\web\Response::FORMAT_JSON;
$response->data = ['message' => 'hello world'];

Yiiは、formatterクラスによって実装された、次のフォーマットをすぐに利用できます。これらのフォーマッタをカスタマイズしたり、新しいフォーマッタを追加するには、yii\web\Response::$formattersプロパティを構成します。

上記のようにレスポンス本文を明示的に設定できますが、ほとんどの場合、アクションメソッドの戻り値によって暗黙的に設定できます。一般的なユースケースは次のようになります。

public function actionIndex()
{
    return $this->render('index');
}

上記indexアクションは、indexビューのレンダリング結果を返します。戻り値はresponseコンポーネントによって取得され、フォーマットされてからエンドユーザーに送信されます。

デフォルトではレスポンスフォーマットがHTMLであるため、アクションメソッドでは文字列のみを返す必要があります。異なるレスポンスフォーマットを使用する場合は、データの返送前に最初に設定する必要があります。例:

public function actionInfo()
{
    \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
    return [
        'message' => 'hello world',
        'code' => 100,
    ];
}

前述のように、デフォルトのresponseアプリケーションコンポーネントを使用するだけでなく、独自のレスポンスオブジェクトを作成してエンドユーザーに送信することもできます。これは、次のようにアクションメソッドでそのようなオブジェクトを返すことで行うことができます。

public function actionInfo()
{
    return \Yii::createObject([
        'class' => 'yii\web\Response',
        'format' => \yii\web\Response::FORMAT_JSON,
        'data' => [
            'message' => 'hello world',
            'code' => 100,
        ],
    ]);
}

注意:独自のレスポンスオブジェクトを作成する場合は、アプリケーション構成でresponseコンポーネントに設定した構成を利用できません。ただし、依存性注入を使用して、新しいレスポンスオブジェクトに共通の構成を適用できます。

ブラウザのリダイレクト

ブラウザのリダイレクトは、Location HTTPヘッダーの送信に依存します。この機能は一般的に使用されるため、Yiiは特別なサポートを提供しています。

yii\web\Response::redirect()メソッドを呼び出すことで、ユーザーのブラウザをURLにリダイレクトできます。このメソッドは、指定されたURLで適切なLocationヘッダーを設定し、レスポンスオブジェクト自体を返します。アクションメソッドでは、そのショートカットバージョンyii\web\Controller::redirect()を呼び出すことができます。例:

public function actionOld()
{
    return $this->redirect('https://example.com/new', 301);
}

上記のコードでは、アクションメソッドはredirect()メソッドの結果を返します。前述のように、アクションメソッドによって返されるレスポンスオブジェクトは、エンドユーザーに送信されるレスポンスとして使用されます。

アクションメソッド以外の場所でyii\web\Response::redirect()を呼び出す場合は、それに続けてyii\web\Response::send()メソッドをチェーン呼び出しして、追加のコンテンツがレスポンスに追加されないようにする必要があります。

\Yii::$app->response->redirect('https://example.com/new', 301)->send();

情報:デフォルトで、yii\web\Response::redirect()メソッドはレスポンスステータスコードを302に設定します。これは、要求されているリソースが別のURIに一時的に配置されていることをブラウザに指示します。ステータスコード301を渡して、リソースが永続的に移動されたことをブラウザに伝えることができます。

現在のリクエストがAJAXリクエストの場合、Locationヘッダーを送信しても、ブラウザが自動的にリダイレクトされるわけではありません。この問題を解決するために、yii\web\Response::redirect()メソッドは、リダイレクトURLを値として持つX-Redirectヘッダーを設定します。クライアント側では、このヘッダー値を読み取ってブラウザを適切にリダイレクトするJavaScriptコードを作成できます。

情報:Yiiには、X-Redirectヘッダーに基づいてブラウザのリダイレクトを含む、一般的に使用されるJavaScriptユーティリティのセットを提供するyii.js JavaScriptファイルが付属しています。したがって、このJavaScriptファイルを使用している場合(yii\web\YiiAssetアセットバンドルを登録することによって)、AJAXリダイレクトをサポートするために何も記述する必要はありません。yii.jsの詳細については、クライアントスクリプトセクションを参照してください。

ファイルの送信

ブラウザのリダイレクトと同様に、ファイルの送信は特定のHTTPヘッダーに依存するもう1つの機能です。Yiiは、さまざまなファイル送信ニーズをサポートするためのメソッドのセットを提供します。これらすべては、HTTP範囲ヘッダーを組み込みでサポートしています。

これらのメソッドは、レスポンスオブジェクトを戻り値として持つ同じメソッドシグネチャを持っています。送信するファイルが非常に大きい場合は、メモリ効率が優れているため、yii\web\Response::sendStreamAsFile()の使用を検討する必要があります。コントローラーアクションでファイルを送信する方法を次の例に示します。

public function actionDownload()
{
    return \Yii::$app->response->sendFile('path/to/file.txt');
}

アクションメソッド以外の場所でファイル送信メソッドを呼び出す場合は、追加のコンテンツがレスポンスに追加されないように、yii\web\Response::send()メソッドも後で呼び出す必要があります。

\Yii::$app->response->sendFile('path/to/file.txt')->send();

一部のWebサーバーには、X-Sendfileと呼ばれる特別なファイル送信サポートがあります。これは、ファイルの要求をWebサーバーにリダイレクトし、Webサーバーがファイルを直接提供するというアイデアです。その結果、Webサーバーがファイルを転送している間、Webアプリケーションは早期に終了できます。この機能を使用するには、yii\web\Response::xSendFile()を呼び出すことができます。次のリストは、いくつかの一般的なWebサーバーでX-Sendfile機能を有効にする方法をまとめたものです。

レスポンスの送信

yii\web\Response::send()メソッドが呼び出されるまで、レスポンスのコンテンツはユーザーに送信されません。デフォルトでは、このメソッドはyii\base\Application::run()の最後に自動的に呼び出されます。ただし、このメソッドを明示的に呼び出して、レスポンスをすぐに強制的に送信することもできます。

yii\web\Response::send()メソッドは、レスポンスを送信するために次の手順を実行します。

  1. yii\web\Response::EVENT_BEFORE_SENDイベントをトリガーします。
  2. yii\web\Response::prepare()を呼び出して、レスポンスデータレスポンスコンテンツにフォーマットします。
  3. yii\web\Response::EVENT_AFTER_PREPAREイベントをトリガーします。
  4. yii\web\Response::sendHeaders()を呼び出して、登録済みのHTTPヘッダーを送信します。
  5. yii\web\Response::sendContent()を呼び出して、レスポンス本文コンテンツを送信します。
  6. yii\web\Response::EVENT_AFTER_SENDイベントをトリガーします。

yii\web\Response::send()メソッドが一度呼び出されると、このメソッドへのそれ以降の呼び出しは無視されます。これは、レスポンスが送信されると、それ以上コンテンツを追加できなくなることを意味します。

yii\web\Response::send()メソッドは、いくつかの便利なイベントをトリガーします。これらのイベントに応答することで、レスポンスを調整したり装飾したりできます。

タイプミスを見つけたか、このページを改善する必要があると思いますか?
Githubで編集する !