ContextSwitchでコンテキストを自作する
先程見たとおり、ContextSwitchには標準で2種類のフォーマットに対応していますが、これ以外にも自分でコンテキストを追加することもできます。例えばプレインテキストを出力するテスト用のコンテキスト「test」を追加するとしましょう。
コンテキストを追加するには「addContext」メソッドを使います。
init()
{
$contextSwitch = $this->_helper->getHelper('contextSwitch');
...
/* コンテキストの作成と追加 */
$contextSwitch->addContext('test', //(1) コンテキストの名前
array('suffix' => 'tst', //(2) 拡張子
'headers' => array('content-type'
=> 'text/plain') //(3)HTTPヘッダ
));
$contextSwitch->addActionContext('context', 'test'); //(4)コンテキストをアクションに関連付け
...
$contextSwitch->initContext();
}
addContextメソッドは2つの引数を取ります。(1)コンテキストの名前と、(2)~(3)オプションです。ここではコンテキストのオプションに(2)ビュースクリプトで使う拡張子と(3)レスポンスで返すHTTPヘッダを指定しています。
この作成したコンテキストを(4)で「context」アクションに関連付けています。これで、contextアクションに「test」コンテキストでアクセスした場合には、今作成したコンテキストで処理されるようになります。
title: Context Switch example Test
ここでリスト7のようなビュースクリプトを準備すると、結果はリスト8のようになります。
http://~/index/context/format/test
▼
title: Context Switch example Test
AJAXリクエストへの出力(AjaxContext)
ContextSwitchアクションヘルパーを利用してJSON形式のデータを送信するアクションを作成していたとしましょう。このときは間違えてこのサービスに通常のブラウザでアクセスしてしまうと、ブラウザはJSON形式のデータをダウンロードしようとして、ダウンロード用のダイアログを表示してしまいます。
これでは使い勝手が悪いので、AJAXのリクエストが来た場合のみにレスポンスを返すアクションヘルパーがAjaxContextアクションヘルパーです。
AjaxContextアクションヘルパーはContextSwitchアクションヘルパーを継承したクラスで、ContextSwitchアクションヘルパーと似たような機能を備えていますがAJAXへのリクエストのみを処理します。また、通常のContextSwitchアクションヘルパーと、次のような違いがあります:
- 通常のContextSwitchアクションヘルパーは、登録されたコンテキストを「contexts」プロパティで管理しますが、AjaxContextアクションヘルパーは「ajaxable」プロパティで管理します。そのため、通常のHTMLを処理するためのContexSwitchアクションヘルパーと共存が可能です。
- AJAXなリクエストでなければ、フォーマット等の条件が一致していたとしてもAjaxContextアクションヘルパーは起動しません。これの判定は、HTTPリクエストのヘッダに「X-Requested-With: XMLHttpRequest」があるかどうかで判定しています。
- AJAXのリクエストに対してHTML形式を送信するためのコンテキスト「HTML」が追加されています。このコンテキストに対応する拡張子は「ajax」です(つまり、対応するビュースクリプトの名前は「~.ajax.phtml」)。
これで、1つのアクションでWebページを出力したり、AJAXへのレスポンスを返したりすることが可能になります。例えば、ギリシャ文字のリストを返す「ajax」コントローラの「items」アクションを考えてみます。リストの内容を通常のWebブラウザで確認したい場合はHTML形式で、オートコンプリート用のAJAXリクエストが来た場合にはJSON形式でレスポンスを返すとしましょう:
class AjaxController extends Zend_Controller_Action
{
public function init()
{
/* (1)AjaxContexの設定 */
$contextSwitch = $this->_helper->getHelper('AjaxContext');
$contextSwitch->addActionContext('items', 'json')//(1-1)
->initContext();
}
...
public function itemsAction()
{
$view = $this->view;
/* (2)リストの準備 */
/* データのキー */
$view->assign('identifier', 'name');
/* データの生成 */
$data = array('alpha','beta','gamma','delta','epsilon','zeta');
$items = array();
foreach ($data as $datum) {
$items[] = array('name' => $datum);
}
/* ビューの変数に割り振り */
$view->assign('items', $items);
}
まず(1)initメソッド内でAjaxContextアクションヘルパーを設定しています。ここでは(1-1)でJSON形式のデータへのリクエストがあった場合にコンテキストを変更するように設定しています。次に(2)itemsアクションではギリシャ文字のリストの準備をしています。
このajaxコントローラのitemsアクションにWebブラウザ等でアクセスすると、ビュースクリプトが実行されHTMLファイルが表示されます。一方で、JavaScript等からフォーマットを「JSON」に指定したリクエストが来ると、AjaxContextアクションヘルパーによってコンテキストが切り替わり、ビューに関連付けられた変数をJSON形式で送信します。
一方で、通常のHTTPリクエストで「http://~/ajax/items/format/json」へアクセスしてもコンテキストの切り替えは起きません。コンテキストの切り替えを起こすためにはHTTPのヘッダに手を入れる必要があります。例えば「wget」という、コマンドラインからHTTPリクエストを行うツールを使い、リクエストのヘッダに「X-Requested-With: XMLHttpRequest」を追加してみます:
$wget -qO- --header="X-Requested-With: XMLHttpRequest" http://localhost/ajax/items/format/json
▼
{"identifier":"name","items":[{"name":"alpha"},...{"name":"zeta"}]}
このように、リクエストヘッダに「X-Requested-With: XMLHttpRequest」が入っていれば出力もJSON形式になります。

