CakePHPでajax更新処理をする

最近、CakePHPを使ってシステムを作る際、ajax更新する処理をよく作るのでその辺のやり方を紹介します。

基本的にajaxで更新したほうが、処理もスムーズでファットコントローラになりずらいというのもあります。

まずはControllerのほうから

通常、scaffoldなどで骨組みを作ると、更新処理はeditメソッドで行われます。

こんな感じですね。

    public function edit($id = null) {
        $this->Post->id = $id;
        if (!$this->Post->exists()) {
            throw new NotFoundException(__('Invalid %s', __('post')));
        }

        //postの場合、更新
        if ($this->request->is('post') || $this->request->is('put')) {

            if ($this->Post->save($this->request->data)) {
                $this->Session->setFlash('処理に成功');
                $this->redirect(array('action' => 'index'));
            } else {
                $this->Session->setFlash('処理に失敗');
            }
        } else {
            //editの画面表示処理
            $this->request->data = $this->Post->read(null, $id);
        }
    }

基本的に更新画面を表示する処理と更新する処理が混在している状態です。

まずはここを分離して、editメソッド内は更新画面の表示処理のみにします。

//分離した処理
public function edit($id = null) {
    $this->Post->id = $id;
    if (!$this->Post->exists()) {
        throw new NotFoundException(__('Invalid %s', __('post')));
    }

    //editの画面表示処理
    $this->request->data = $this->Post->read(null, $id);
}

edit画面の表示処理だけなので、かなりスッキリしました。

続いて、更新処理を別メソッドで書きます。

こんな感じ

    function ajax_edit(){

        $this->autoRender = false;

        if ($this->request->is('ajax')) {
            try {

                if(!$this->Post->save($this->request->data)){
                    throw new Exception('処理に失敗');
                }
                $data['is_error'] = false;
                $data['message'] = '処理に成功';
                $this->Post->commit();

            } catch (Exception $e) {
                $data['is_error'] = true;
                $data['message'] = $e->getMessage();
                $this->Post->rollback();
            }
            echo json_encode($data);
        }
    }

この書き方は実は、どんな更新画面でもほとんどかわることがないので、使い回しが楽です。
try-catchにすることで、save処理をモデル内に移した場合でも、エラー処理が簡単になります。
複数のモデルを更新する場合などは、処理が深くなるので、try-catchのほうが綺麗に書けます。

続いてViewですが、

基本的には一緒で、submitボタンを通常のボタンにして、ajaxでリクエストを飛ばすようにします。

通常の更新処理

<!-- 通常の更新処理 -->
<?php echo $this->Form->create('Post');?>

<!--インプット項目-->
<?php echo $this->Form->input('name');?>

<!--更新ボタン-->
<?php echo $this->Form->Submit('更新');?>

ajaxに変更処理を変更する

<!--ajaxの更新処理 -->
<?php echo $this->Form->create('Post');?>

<!--インプット項目-->
<?php echo $this->Form->input('name');?>

<!--更新ボタン-->
<button type="button" id="ajax_edit" >更新 </button>

そして実際にjqueryでajax処理を書きます。


<script type="text/javascript">

    $(function(){
        //buttonをクリックした場合、
        $(document).on('click', '#ajax_edit', function () {

            //ボタンを無効化
            $('#ajax-edit').attr('disabled', true);
            //ajax_editメソッドを呼び出す
            $.post('/posts/ajax_edit', $('form').serialize(), function (rs) {

                //ボタンを戻す
                $('#ajax-edit').attr('disabled', false);
         //処理結果がjson形式で返ってくるのでparseする
                var data = JSON.parse(rs);
                if (data.is_error) {
                    //エラー処理
                    $('#message_area').append(data.message);
                    //エラー時の処理を色々書く
                        〜〜〜〜
                } else {
                    //メッセージ出力
                    $('#message_area').append(data.message);
                    //正常処理を色々書く
                        〜〜〜〜
                }

            })
        });
    });

</script>

結構簡単です。

これでOKです。
色々と更新処理はajaxで行うと、処理が煩雑にならず便利です。