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

HTMLとJSONのAPI CakePHP

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の実装でした。

CakePHPWebAPI
スポンサーリンク
この記事が気に入ったら
いいね!しよう
最新情報をお届けします。
この記事を書いた人

スパイスファクトリー株式会社 Webエンジニア。フロントエンドやWebサイトの高速化が得意です。インフラ・バックエンドも一通りやってます。
個人的なお仕事のご依頼や情報交換などはお問い合わせまたはTwitterにメンションをお願いします。

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

コメント

タイトルとURLをコピーしました