Hatena::ブログ(Diary)

憂鬱なプログラマの形而上学 RSSフィード

2010-01-06

cakePHP+ajaxでjsonを扱う

cakePHPajaxjsonを扱ってみたのでその備忘録。

まずはコントローラー側で必要なヘルパーコンポーネントを追加する。

ちなみに view でprototype.js を読み込んでいるがそこは省略w

app/controllers/hoge.php

class HogeController extends AppController {
	var $helpers = array("Javascript");		/* 取りあえずは Javascriptヘルパーが必要 */
	var $components = array("RequestHandler");		/* RequestHandlerコンポーネントが必要 */
	
	/* コントローラのメソッドなど ... */
}
?

あれ?Ajaxヘルパーは?と思った方もいるだろうけど、AjaxヘルパーはどちらかというとAjaxでリクエストを送ったりする時のものなので、jsonとは直接関係ない。だから、Ajaxヘルパーを使うかどうかはお好みだが、私自身は直接javascriptAjax.request()メソッドを呼んでいる。(その方が複雑なこともやりやすい)

次に、Ajaxでリクエストを送ってjsonを取得する部分。hogeコントローラーのsampleアクションで実行する。また、jsonデータを取得するアクションをjsonとする。

app/controllers/hoge.php

<?php

class HogeController extends AppController {
	var $helpers = array("Javascript");		/* 取りあえずは Javascriptヘルパーが必要 */
	var $components = array("RequestHandler");		/* RequestHandlerコンポーネントが必要 */
	
	function sample() {
		/* お好きな処理 */
	}
	/* コントローラのメソッドなど ... */
}
?>

sampleアクションのテンプレートで、リンクをクリックすると/hoge/jsonにリクエストされるようにしてみる。

app/views/hoge/sample.ctp

<script type="text/javascript">
window.onload = function() {
	Event.observe("sample","click",function() {
		new Ajax.Request(
			'/hoge/json' , 
			{
				method:		"get" , 
				onSuccess: function (req) {
					var res;
					eval("res = "+ req.responseText );
					// res.result という値があればalertで表示
					if (res.result) { 
						alert(res.result);
					}
				} , 
				onFailure: function(req) { 
					alert('読み込みに失敗しました'); 
				}, 
				onException: function (req) { 
					alert('不正な値を取得しました。'); 
				} 
			}
		);
	});
}


</script>
<a href="javascript:void(0);" id="sample">sample</a>

最後に/hoge/jsonAjaxでリクエストされたら、jsonデータを返すようにしてみる。

まずはコントローラーのbeforeFilter()でjson用のHTTPヘッダーを出力。beforeFilter()で実行しないと動かなかったので注意。ついでにjsonアクションのメソッドを追加。

app/controllers/hoge.php

<?php
class HogeController extends AppController {
	var $helpers = array("Javascript");		/* 取りあえずは Javascriptヘルパーが必要 */
	var $components = array("RequestHandler");		/* RequestHandlerコンポーネントが必要 */
	
	function beforeFilter() {
		/* お好きな処理 */
		
		// ajax:json の場合
		if ($this->RequestHandler->isAjax()) {
			// action が jsonの場合
			if ($this->action === "json") {
				$this->layout = "ajax";
				Configure::write("debug" , 0);
				$this->RequestHandler->setContent("json");
				$this->RequestHandler->respondAs('application/json; charset=UTF-8');
			}
		}
	}
	function sample() {
		/* お好きな処理 */
	}
	function json() {
		// テンプレートに result 変数をセット
		$this->set("result" , array("result" => "OK"));
	}
	/* コントローラのメソッドなど ... */
}
?>

最後にjsonアクションのviewでjsonデータを出力する。これはjavascriptヘルパーのobject()メソッドで一発でできる。

<?= $javascript->object($result) ?>

以上で、リンクをクリックすると[OK] と表示されます。

こんな感じでPHP連想配列配列をそのままjavascriptに渡すことができるので、管理画面などで複雑な処理をする場合に便利です。

ちなみに、Ajaxで後から要素のinnerHTMLを変えると、IE7ではそのinnerHTMLの中の要素にCSSが適応されない、というバグがあったので(もしかしたらケースバイケースかも知れませんが、、)その場合には、jsonでデータを受け取って、javascriptdomを足していくとうまくいくことが何度かあった。それ以来、面倒なので、Ajaxのデータの受け渡しは基本的にjsonで行うようにしている。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/k_yamamot/20100106/1262749977