AjaxContext を使ってみる。

Phwittr ではメッセージのポストに Ajax を使用するという仕様なので、AjaxContext を試してみた。


AjaxContext は ContextSwitch ヘルパーを継承したもの。
ContextSwitch については、wads-blog さんが非常に分かりやすく解説されている。
# いつも参考にさせて貰ってます。
[Zend Framework] Zend_ControllerアクションヘルパーのContextSwitch – wadslog


ContextSwitch はパラメータによって応答する形式を自動的に設定してくれる。
# Smarty で扱う場合は少々改造しないといけないよう。今回は Zend_View で試した。


呼出し側はこんな感じで書いた。
# prototype.js 使った。JavaScript は得意じゃない・・・ orz

<script type="text/javascript">
//<![CDATA[
function updateComment() {
    new Ajax.Request(
        '/index/update?format=json',
        {                    
            method:'post',   
            parameters: Form.serialize('update'),
            onComplete: function(httpObj){
                $("comment").innerHTML = httpObj.responseText;
            }
        }
    );
}
//]]>
</script>
<form="/index/update" id="update" method="post" onsubmit="updateComment();">
  <input type="text" cols="40" id="status" name="status" />
  <input type="button" onclick="$('update').onsubmit();" id="submit" value= "投稿する" />
</form>
<div id="comment"></div>

コントローラ側
IndexController.php
# 直接テンプレートにアサインしてるけど、バリデートしている前提で・・。

<?php
class IndexController extends Zend_Controller_Action
{
    public function init()
    {   
        parent::init();
        $ajaxContext = $this->_helper->getHelper('ajaxContext');
        $ajaxContext->addActionContext('update', array('html', 'json'))
                    ->initContext();
    }
    public function updateAction()
    {   
        $this->assign('status', $this->_getparam('status'));
    }
}

テンプレート
index/update.ajax.phtml

<?php echo $this->escape($status) ?>

Ajax でポスト先に指定しているパラメータを format=json とすると json で応答され、format=html とすると、html が返ってくる。
注意点としては format=html とした場合は、新たに アクション名.ajax.phtml というテンプレートファイルを作成する必要がある。
json 形式の場合は、デフォルトでは勝手にシリアライズして、応答するので、テンプレートは不要。


これで実際に動かしてみたところ、レイアウトファイルがまるまる応答された。
ドキュメントを読んでみると、レイアウトファイルを使用している場合は無効にしろとある。

いずれかを有効にするには、コントローラに対して 「どのアクションがどのコンテキストに対応するのか」 を教えてやる必要があります。 やってきたリクエストがそのアクションで有効なコンテキストである場合、 ヘルパーが行う処理は次のようになります。

  • レイアウト機能が有効な場合に、それを無効にする。
http://framework.zend.com/manual/ja/zend.controller.actionhelpers.html#zend.controller.actionhelpers.contextswitch

現在受けたリクエストが Ajax によるポストかどうか判定するには、リクエストオブジェクトのメソッドで判定が出来る。

<?php
$request = $this->getRequest();
if ($request->isXmlHttpRequest()) {
    $this->helper->layout->disableLayout();
}

上記をコントローラの init() や preDispatch() に記述すると、レイアウト機能が無効になる。
なお ViewRenderer を使用している場合、コントローラにひもづいているテンプレートは自動的に無効になる。
ViewRenderer を使用しない場合は、テンプレートの読み込みを無効にしないといけないのかも。。。
# この場合だと、index/update.phtml


レイアウトを無効にしわすれててハマったけど、簡単なコードで Ajax のレスポンスが出来る!