リクエストハンドリング

class RequestHandlerComponent(ComponentCollection $collection, array $settings = array())

リクエストハンドラコンポーネントは、 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');

    // 以下略
}

リクエスト情報の取得

リクエストハンドラはクライアントやリクエストについての情報を提供するいくつかのメソッドがあります。

RequestHandlerComponent::accepts($type = null)

$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 の場合に実行される
        }
    }
}

ほかのリクエスト「型」の検出については、次のとおりです。:

RequestHandlerComponent::isXml()

現在のリクエストが応答として XML を受け入れる場合は true を返します。

RequestHandlerComponent::isRss()

現在のリクエストが応答として RSS を受け入れる場合は true を返します。

RequestHandlerComponent::isAtom()

現在のリクエストが応答として Atom を受け入れる場合は true を返します。 受け入れなければ false

RequestHandlerComponent::isMobile()

ユーザエージェントにモバイルブラウザの文字列を含む場合、もしくはクライアントが WAP コンテンツを受け入れる場合は true モバイルブラウザの User Agent 文字列は:

  • Android
  • AvantGo
  • BlackBerry
  • DoCoMo
  • Fennec
  • iPad
  • iPhone
  • iPod
  • J2ME
  • MIDP
  • NetFront
  • Nokia
  • Opera Mini
  • Opera Mobi
  • PalmOS
  • PalmSource
  • portalmmm
  • Plucker
  • ReqwirelessWeb
  • SonyEricsson
  • Symbian
  • UP.Browser
  • webOS
  • Windows CE
  • Windows Phone OS
  • Xiino
RequestHandlerComponent::isWap()

クライアントが WAP コンテンツを受け入れる場合は true

上記の全ての検出メソッドは、コンテンツタイプの特定するフィルタ機能と同様の方法で使用できます。 例えば、 Ajax のリクエストに応答するときには、頻繁にデバッグレベルを変更しブラウザのキャッシュを無効にしたいでしょう。 しかし、非 Ajax リクエストのときは反対にキャッシュを許可したいと思います。 そのようなときは次のようにします。:

if ($this->request->is('ajax')) {
    $this->disableCache();
}
// コントローラのアクションの続き

クライアントについての追加情報を取得する

RequestHandlerComponent::getAjaxVersion()

Ajax の呼び出しの場合は、 Prototype のバージョンを取得し、それ以外は空文字列になります。 Prototype は、 “Prototype version” という特別な HTTP ヘッダをセットします。

リクエストデータの自動デコード

RequestHandlerComponent::addInputType($type, $handler)
パラメタ:
  • $type (string) – デコーダを紐づけるコンテンツタイプのエイリアス(例、 ‘json’ 、 ‘xml’ )
  • $handler (array) – $type のためのハンドラ

リクエストデータのデコーダを追加します。 ハンドラはコールバックと、コールバックのための追加の変数を含めておくべきです。 コールバックはリクエストの入力に含まれるデータの配列を返す必要があります。 たとえば、コントローラの 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 なしになります。

リクエストへの応答

リクエストの検出に加え、リクエストハンドラはアプリケーションが出力やコンテンツタイプのマッピングの変更を簡単にする機能も提供します。

RequestHandlerComponent::setContent($name, $type = null)
  • $name string - Content-type の名前かファイルの拡張子(例、 html, css, json, xml )
  • $type mixed - Content-type に紐づけられる mime-type

setContent は、 $name の Content-type を追加(設定)します。 コンテンツタイプには、分かりやすいエイリアスや拡張子を割り当てることができます。 これにより、リクエストハンドラはスタートアップメソッドの中で、自動的にリクエストの型に応じたレスポンスを判別します。 Router::parseExtension を使用する場合、コンテンツタイプの名前として拡張子を使うようにするべきです。 さらにそれらのコンテンツタイプは、 prefers() と accepts() で使われます。

コンテンツタイプの別名に対する自動的な動作の変更を効果的に行えるよう、setContent は、コントローラの beforeFilter() 内で使用されるのが最適です。

デフォルトのマッピング:

  • javascript text/javascript
  • js text/javascript
  • json application/json
  • css text/css
  • html text/html, */*
  • text text/plain
  • txt text/plain
  • csv application/vnd.ms-excel, text/plain
  • form application/x-www-form-urlencoded
  • file multipart/form-data
  • xhtml application/xhtml+xml, application/xhtml, text/xhtml
  • xhtml-mobile application/vnd.wap.xhtml+xml
  • xml application/xml, text/xml
  • rss application/rss+xml
  • atom application/atom+xml
  • amf application/x-amf
  • wap text/vnd.wap.wml, text/vnd.wap.wmlscript, image/vnd.wap.wbmp
  • wml text/vnd.wap.wml
  • wmlscript text/vnd.wap.wmlscript
  • wbmp image/vnd.wap.wbmp
  • pdf application/pdf
  • zip application/x-zip
  • tar application/x-tar
RequestHandlerComponent::prefers($type = null)

クライアントが好むコンテンツタイプを確定します。 もしパラメータをセットしなければ、最も優先度の高いコンテンツタイプが返されます。 $type を配列で渡した場合、クライアントが受け付けるものとマッチした最初の値が返されます。 優先度はまず、もし Router で解析されたファイルの拡張子により確定されます。 次に、 HTTP_ACCEPT にあるコンテンツタイプのリストから選ばれます。

RequestHandlerComponent::renderAs($controller, $type)
パラメタ:
  • $controller (Controller) – コントローラの参照
  • $type (string) – コンテンツを描画する、使いやすいコンテンツタイプの名前。例えば xml や rss 。

任意の型でコントローラの出力のモードを変更します。 また、適切なヘルパーが存在し、それがコントローラ中のヘルパー配列で指定されていなければ、これを追加します。

RequestHandlerComponent::respondAs($type, $options)
パラメタ:
  • $type (string) – xml や rss といったコンテンツタイプの名前か、 application/x-shockwave といった完全な名前
  • $options (array) – 指定したコンテンツタイプが複数のコンテンツに関連付いている場合、どれを使うかを $index で指定します。

コンテンツタイプにマップした名前に基づき、応答するヘッダをセットします。

RequestHandlerComponent::responseType()

現在の応答するコンテンツタイプのヘッダをの型を返します。もしセットされていなければ null を返します。

HTTP キャッシュバリデーションの活用

バージョン 2.1 で追加.

HTTP キャッシュバリデーションモデルは、クライアントへのレスポンスにコピーを使用するかどうかを判断する(リバースプロキシとして知られる)キャッシュゲートウェイを使用する処理です。 このモデルでは、主に帯域幅を節約しますが、正しく使用することで応答時間の短縮や、いくつかのCPUの処理を節約することができます。

コントローラでリクエストハンドラを有効化するとビューが描画される前に、自動的にチェックを行います。 このチェックでは、前回クライアントが要求してからレスポンスに変更がないかを判断するため、レスポンスオブジェクトと元のリクエストを比較します。

レスポンスが変更無いと見なされる場合、ビューの描画処理は行われず、クライアントには何も返さず処理時間を短縮、帯域幅を節約します。 レスポンスステータスコードは 304 Not Modified にセットされます。

自動的なチェックは、 checkHttpCache を false にすることで行わないようにすることができます。:

public $components = array(
    'RequestHandler' => array(
        'checkHttpCache' => false
));

カスタム ViewClasses の利用

バージョン 2.3 で追加.

JsonView/XmlView を利用する場合、カスタムビュークラスの優先順位をデフォルトの順番から上書きしたり、独自のカスタムクラスを追加したい場合があるでしょう。

その場合、既存のタイプや新規タイプのクラスをマッピングすることができます。

RequestHandlerComponent::viewClassMap($type, $viewClass)
パラメタ:
  • $type (string|array) – タイプ名の文字列または配列 array('json' => 'MyJson') のフォーマット
  • $viewClass (string) – View を取り除いたビュークラス名

viewClassMap を使って、自動的にセットすることも可能です。

public $components = array(
    'RequestHandler' => array(
        'viewClassMap' => array(
            'json' => 'ApiKit.MyJson',
            'xml' => 'ApiKit.MyXml',
            'csv' => 'ApiKit.Csv'
        )
));