このエントリーが役に立ったらシェアをお願いします!

CakePHPでHTMLの入ったJSONを返すAPIを作ってみた

このエントリーが役に立ったらシェアをお願いします!

CakePHP御存知の通りはControllerとModelで処理を書いていき、そこからViewをレンダーします。
ですが先日、Ajaxのレスポンスで処理結果のステータスとHTMLの両方をJSONで返したい!ということがありました。

こういう場合はViewでヒアドキュメントを利用すればゴリゴリ書くことも可能ですがメンテナンス性が低下します(後述)
今回はControllerの中でViewをレンダーし、HTMLをController内で扱う方法をご紹介します。

スポンサーリンク

Viewを正しく使ってJSONを返却する

恐らくこれが正攻法だと思います。ですがメンテナンス性としてもあまり好きではありません。Controller側ではLayoutのレンダーを無効化し、アクションのViewのみをレンダーさせています。また、CakeResponse($this->response)でContentTypeをapplication/jsonに指定しています。

class TestController extends AppController {
  public function json_response() {
      $this->autoLayout = false;
      // JSON形式
      $this->response->type('json');
  }
}

これに対し、ViewではヒアドキュメントでHTML記述し、json_encodeしています。

$html = <<<HTML
<div>
  <p>なんかのダイアログ</p>
  <button>閉じる</button>
</div>
HTML;
echo json_encode(array(
  'status' => '成功しました',
  'html' => $html
));

ヒアドキュメントで書かなくとも外部ファイル(Element)に切ったり、ViewBlockを使って$htmlに入れてしまう方法もあると思います。

echo json_encode(array(
  'status' => '成功したよ!',
  'html' => $this->element('dialog')
));

でも、なんか違うじゃん!ヒアドキュメントとか美しくないじゃん!
Elementでも外部ファイルいちいち切ったらファイル増えるじゃん!
Viewがこれだとメンテナンスもよろしくないですね。
json_encodeとかしちゃってるのもViewのお仕事ではない気がします。個人的に。

Controller上でレンダーしたViewのHTMLを取得する

今回はViewにダイアログのHTMLを記述して、Controller上でそのViewをレンダーしながらjsonで固める処理を書きます。
Controller上でのみ処理を完結させます。

<div>
  <p>なんかのダイアログ</p>
  <button>閉じる</button>
</div>
class TestController extends AppController {

    public function ajaxTest() {
        // Viewのレンダーを無効化
        $this->autoRender = false;
        // ContentTypeをJSONにする
        $this->response->type('json');
        // Viewを生成。Controllerの状態が引き継がれる
        $View = new View($this);
        // $View->viewPath = 'Viewのフォルダ名';
        $View->set('Viewに渡す変数名', '変数値');
        $html = $View->render('ajax_test', false);
        return json_encode(array(
                'status' => '成功したよ!',
                'html' => $html
        ));
    }
}

Controllerの$autoRenderをfalseにするとreturnの値をレスポンスにすることができます。これを利用してjson形式のデータを返しています。
View::viewPathにはControllerの名前がデフォルトで入るので、必要に応じてフォルダを指定します。
View::render()の第一引数はviewファイル名,第二引数にはレイアウトファイル名を指定します。
レイアウトを使用しない場合は第二引数にfalseを渡してください。

これでJSONのレスポンスにHTMLを含めることができました。
json形式のレスポンス

以上、少し裏ワザ的な手法ですが個人的にしっくりくるAPIの実装でした。

スポンサーリンク

このエントリーが役に立ったらシェアをお願いします!

1この記事を書いた人
ShoheiTai
フロントエンド志向のWebエンジニア。
HTML5やWeb高速化、SEO等のフロントエンド開発が大好物。
バックエンドではCakePHP,Wordpress開発を主戦場としています。
Web開発のスパイスファクトリー株式会社創業メンバー。

CakePHPでHTMLの入ったJSONを返すAPIを作ってみた
イケてないコード - Webエンジニアのブログの
最新情報をいいねしてチェックしよう!