某所で僕が質問&自己レスして自己完結した某トピックをまとめておきます。
たとえば表示中のWebページからAJAXでサーバーにアクセスして、サーバー側ではリクエスト内容に応じたJSON文字列を構成して出力する、といった処理を書く場合。
出力したいJSON文字列が単純に、
みたいな構造なのであれば、サーバー側の処理もシンプルに
$this->autoRender = false;
$this->layout = 'ajax';
header("Content-type:application/json; charset=UTF-8");
echo json_encode(array('result' => true, 'value' => 1));
とでもすればいい。この処理はたぶんCakePHP2系でもそのまま使えるんじゃないかと思います。
問題は、ここで
みたいなJSON文字列を出力したい場合。
複雑なHTML文字列を準備する必要がある以上、CakePHP本来のrender()機能を活用して、ちゃんと
$this->render();
といった描画処理を行い、その結果生成されるHTML文字列を取得して、それをJSON文字列の一部として組み込んで出力したいわけです。
ここで本題。
CakePHP1.3では、コントローラーのrender()で描画したHTMLをそのまま出力せずに、アクション内で取得して使いたい場合、その処理は以下のようなコードで簡単に実現できました。
$this->set(aray('var1' => 'value1', 'var2' => 'value2'));
// ヘッダやデバッグ情報など不要な文字列の出力を抑止
Configure::write('debug', 0);
$this->layout = 'ajax';
// 描画結果の取得
$html = $this->render();
// render()結果の出力を解除
$this->output = null;
// JSON形式で出力
header("Content-type:application/json; charset=UTF-8");
echo json_encode(array('result' => true, 'html' => $html));
ところがこの書き方、CakePHP2.0ではまったく機能しません。
具体的に何が変わったかといえば、render()の戻り値はHTML文字列じゃなくオブジェクトになっちゃってるし、コントローラーのoutputプロパティに至ってはそもそも存在しないしと、それはそれは劇的な変更があった様子。
Web上にもあまり参考になる資料がなくて正直、困り果てました。
ソースを追っかけたりして苦労した末見つけた代替のコードは、以下の通りです。ほかにもやり方あるかもしれないけど、誰かの参考になれば。
$this->render();
$this->response->type('json');
$this->response->body(json_encode(array(
'result' => true,
'html' => $this->response->body()
)));
return $this->response;
} // ※end of function
「$this->response->type(‘json’);」とすることでデバッグ文字列の抑止やヘッダーの追加は勝手にやってくれるようです。アクションの最後にController->responseオブジェクトを返すという処理が特徴的で、これを元に実際の出力が行われる、という挙動らしい。













