リクエストハンドラコンポーネントは、 HTTP リクエストについての追加情報を取得するために使われます。 クライアントが受付けるコンテンツタイプを得ることや、(設定している場合)拡張子にあわせたレイアウトファイルに自動的に変更することだけでなく、コントローラに Ajax についての情報を渡すことも可能です。
リクエストハンドラは初期状態で、多くの JavaScript ライブラリが使用している HTTP-X-Requested-With ヘッダに基づいた Ajax リクエストを自動的に判定します。 Router::parseExtensions() と組み合わせて使用することで、リクエストハンドラはリクエストの種類に応じて自動的にレイアウトとビューのファイルを切り替えます。 さらに、リクエストの拡張子と同じ名前のヘルパーが存在する場合、コントローラのヘルパーの設定をする配列に加えます。 また、 XML/JSON データをコントローラへ POST した場合、自動的に解析され $this->request->data の配列に割り当てられ、モデルデータとして保存可能です。 リクエストハンドラを利用するためには $components の配列に含めてください。:
class WidgetController extends AppController {
public $components = array('RequestHandler');
// 以下略
}
リクエストハンドラはクライアントやリクエストについての情報を提供するいくつかのメソッドがあります。
$type は、文字列・配列・ null のいずれかです。 文字列の場合、そのコンテンツタイプをクライアントが受付ける場合に true を返します。 配列の場合、そのなかのひとつを受付ける場合に true を返します。 null の場合、クライアントが受付けるコンテンツタイプをすべて配列で返します。 例:
class PostsController extends AppController {
public $components = array('RequestHandler');
public function beforeFilter() {
if ($this->RequestHandler->accepts('html')) {
// クライアントが HTML (text/html) のレスポンスを受付ける場合のみ実行されます
} elseif ($this->RequestHandler->accepts('xml')) {
// XMLのみ実行するコード
}
if ($this->RequestHandler->accepts(array('xml', 'rss', 'atom'))) {
// XML か RSS か Atom の場合に実行される
}
}
}
ほかのリクエスト「型」の検出については、次のとおりです。:
現在のリクエストが応答として XML を受け入れる場合は true を返します。
現在のリクエストが応答として RSS を受け入れる場合は true を返します。
現在のリクエストが応答として Atom を受け入れる場合は true を返します。 受け入れなければ false
ユーザエージェントにモバイルブラウザの文字列を含む場合、もしくはクライアントが WAP コンテンツを受け入れる場合は true モバイルブラウザの User Agent 文字列は:
クライアントが WAP コンテンツを受け入れる場合は true
上記の全ての検出メソッドは、コンテンツタイプの特定するフィルタ機能と同様の方法で使用できます。 例えば、 Ajax のリクエストに応答するときには、頻繁にデバッグレベルを変更しブラウザのキャッシュを無効にしたいでしょう。 しかし、非 Ajax リクエストのときは反対にキャッシュを許可したいと思います。 そのようなときは次のようにします。:
if ($this->request->is('ajax')) {
$this->disableCache();
}
// コントローラのアクションの続き
Ajax の呼び出しの場合は、 Prototype のバージョンを取得し、それ以外は空文字列になります。 Prototype は、 “Prototype version” という特別な HTTP ヘッダをセットします。
パラメタ: |
|
---|
リクエストデータのデコーダを追加します。 ハンドラはコールバックと、コールバックのための追加の変数を含めておくべきです。 コールバックはリクエストの入力に含まれるデータの配列を返す必要があります。 たとえば、コントローラの beforeFilter に CSV ハンドラを追加する場合:
$parser = function ($data) {
$rows = str_getcsv($data, "\n");
foreach ($rows as &$row) {
$row = str_getcsv($row, ',');
}
return $rows;
};
$this->RequestHandler->addInputType('csv', array($parser));
上述の例は PHP 5.3 が必要です。 しかしながら、ハンドラの関数としては、どの callable も利用できます。 コールバックにはどのような引数を渡すこともでき、これは json_decode のようなコールバックのときに便利です:
$this->RequestHandler->addInputType('json', array('json_decode', true));
上述の例は、 JSON によるデータを $this->request->data の配列にします。 StdClass オブジェクトで取得したい場合は、引数の true なしになります。
リクエストの検出に加え、リクエストハンドラはアプリケーションが出力やコンテンツタイプのマッピングの変更を簡単にする機能も提供します。
setContent は、 $name の Content-type を追加(設定)します。 コンテンツタイプには、分かりやすいエイリアスや拡張子を割り当てることができます。 これにより、リクエストハンドラはスタートアップメソッドの中で、自動的にリクエストの型に応じたレスポンスを判別します。 Router::parseExtension を使用する場合、コンテンツタイプの名前として拡張子を使うようにするべきです。 さらにそれらのコンテンツタイプは、 prefers() と accepts() で使われます。
コンテンツタイプの別名に対する自動的な動作の変更を効果的に行えるよう、setContent は、コントローラの beforeFilter() 内で使用されるのが最適です。
デフォルトのマッピング:
クライアントが好むコンテンツタイプを確定します。 もしパラメータをセットしなければ、最も優先度の高いコンテンツタイプが返されます。 $type を配列で渡した場合、クライアントが受け付けるものとマッチした最初の値が返されます。 優先度はまず、もし Router で解析されたファイルの拡張子により確定されます。 次に、 HTTP_ACCEPT にあるコンテンツタイプのリストから選ばれます。
パラメタ: |
|
---|
任意の型でコントローラの出力のモードを変更します。 また、適切なヘルパーが存在し、それがコントローラ中のヘルパー配列で指定されていなければ、これを追加します。
パラメタ: |
|
---|
コンテンツタイプにマップした名前に基づき、応答するヘッダをセットします。
現在の応答するコンテンツタイプのヘッダをの型を返します。もしセットされていなければ null を返します。
バージョン 2.1 で追加.
HTTP キャッシュバリデーションモデルは、クライアントへのレスポンスにコピーを使用するかどうかを判断する(リバースプロキシとして知られる)キャッシュゲートウェイを使用する処理です。 このモデルでは、主に帯域幅を節約しますが、正しく使用することで応答時間の短縮や、いくつかのCPUの処理を節約することができます。
コントローラでリクエストハンドラを有効化するとビューが描画される前に、自動的にチェックを行います。 このチェックでは、前回クライアントが要求してからレスポンスに変更がないかを判断するため、レスポンスオブジェクトと元のリクエストを比較します。
レスポンスが変更無いと見なされる場合、ビューの描画処理は行われず、クライアントには何も返さず処理時間を短縮、帯域幅を節約します。 レスポンスステータスコードは 304 Not Modified にセットされます。
自動的なチェックは、 checkHttpCache を false にすることで行わないようにすることができます。:
public $components = array(
'RequestHandler' => array(
'checkHttpCache' => false
));
バージョン 2.3 で追加.
JsonView/XmlView を利用する場合、カスタムビュークラスの優先順位をデフォルトの順番から上書きしたり、独自のカスタムクラスを追加したい場合があるでしょう。
その場合、既存のタイプや新規タイプのクラスをマッピングすることができます。
パラメタ: |
|
---|
viewClassMap を使って、自動的にセットすることも可能です。
public $components = array(
'RequestHandler' => array(
'viewClassMap' => array(
'json' => 'ApiKit.MyJson',
'xml' => 'ApiKit.MyXml',
'csv' => 'ApiKit.Csv'
)
));