CakePHP 2.x JSヘルパーでajax通信(ajax helperは使わない)

Shunsuke Sawada

本日の目標が一段落したので、
ビールのみながら技術メモです。

やりたいこと

コメントフォーム。
送信ボタンを押すと、メッセージはデータベースに保存され、
リダイレクトなしで送信完了のメッセージを出す。

まぁこれは一例で、実際の使い方はいろいろ。

画面遷移せずに…
•TODOリストを追加する
•ON/OFFを切り替える
•記事を削除する

とかね。

ヘルパー

AJAXヘルパーってあるんだけど今回は使いません。
AJAX helper

こんなのあるよって教えてもらったんだけど、
更新されてないっぽいしね。2.xでも使えるのは確認してますが。
ダウンロードしてインストールする必要もある。

CakePHPに標準であるJsHelperでできるので、こっちでやります。
JsHelper

コーディング

jQueryはあらかじめ読み込んでおいてください。

app/view/messages/index.ctp

php
1
2
3
4
5
6
7
8
9
10
11
12
<? php
echo $this->Form->create();
echo $this->Form->input('name');
echo $this->Form->input('email');
echo $this->Form->input('message');
echo $this->Js->submit('Send', array(
    'before'=>$this->Js->get('#sending')->effect('fadeIn'),
    'success'=>$this->Js->get('#sending')->effect('fadeOut'),
    'update'=>'#success'
));
echo $this->Form->end();
?>

でどこかに下のようなdivを置いておく。

1
2
div#success
div#sending

  
だいたい通常通りですが、
$this->Form->submit ではなく、
$this->Js->submit としています。

FormHelperがとるオプションはすべて渡せるし、
追加で色々なオプションを渡すことができます。

●before 送信ボタンを押した後にすること(“送信中...”とかを表示する)
div id="sending を出す
●success 送信完了したあとにすること(“送信中...”とかを消す)
div id="sending を消す
●update 処理が終わった後にここで指定した要素の中身を書き換えます
div id="success" は今は空っぽだけど、送信後に何か入ります。

そうすると、Jsヘルパーがjavascriptを作ってくれます。
作ってくれるんだけど、このままでは出力される場所があませんので指定してあげます。
下記をbody閉じタグの直前に書く。

1
<? php echo $this->Js->writeBuffer(); ?>

そうすると、JsHelperで作られたすべてのスクリプトがここに出力される。

でもそうされると困る場合もあるので、そんな時はオプションに
'buffer' => false
を追加しましょう。そうするとフォームが出力されたすぐ後にjavascriptが出力されます。

MessagesController.ctp

php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<? php
class MessagesController extends AppController {
    public $helpers = array('Js');
    public $components = array('RequestHandler');

    public function index() {
        //データが空でないかチェック
        if (!empty($this--->data)) {
            //もし保存がうまくいったら
            if ($this-&gt;Message-&gt;save($this-&gt;data)) {
                //もしリクエストがajaxだったら
                if ($this-&gt;RequestHandler-&gt;isAjax()) {
                    //ajaxレイアウトを使って、success.ctpを出力
                    $this-&gt;render('success', 'ajax');
                }
                //(念のため)リクエストがajax以外なら
                else {
                        //メッセージをセットしてリダイレクト
                    $this-&gt;Session-&gt;setFlash('Message sent');
                    $this-&gt;redirect(array('action'=&gt;'index'));
                }
            }
        }
    }
}

public $helpers = array('Js');
でJSヘルパーを読み込む。
JSじゃないですよ。コードには'Js'と書いてください。

public $components = array('RequestHandler');
はリクエストがajaxかどうか判別するのに必要です。

$this->render('success', 'ajax');
ここがポイントすね。

successはビューファイル。ajaxはレイアウトファイルです。
app/view/messages/success.ctp の内容が
app/view/messages/index.ctp の div id="success" の中に出力されます。

app/view/Layouts/ajax.ctp

1
2
<!--これだけ-->
<? php echo $this -> fetch('content'); ?>

app/view/messages/success.ctp

1
2
<!--送信完了メッセージ-->
メッセージが送信されました!

以上です。

1.メッセージを入力
2.送信ボタンをクリック
3.“送信中...”を表示
4.“送信中...”が消える
5.メッセージがデータベースに保存される
6.送信完了をお知らせ

という流れになるはず。

参考ビデオ

とても分かりやすいです。英語だけど。
Cakephp Ajax Tutorial - Using Cakephp's Js Helper and jQuery

20
Shunsuke Sawada

おすすめの記事

チャット構築にトライして今日一日ガンバった結果をこっそりメモしよう。
RSpec Capybara Webkit Xvfb CentOS 要するにRailsでjavascriptをテストしたい
30
Turbolinks で Google adsense が正しく表示されない時の対処方法
5