5
6

More than 5 years have passed since last update.

CakePHP3のページネーションをAjaxで行う

Last updated at Posted at 2018-12-14

CakePHP3で通常のページネーションのように画面を再表示せず、Ajaxで一覧部分だけを切り替える方法を紹介したいと思います。

バージョン

CakePHP 3.6

画面

高校野球の歴代優勝校の一覧を作ったので、これを例にします。
base.png

データ

high_schoolsテーブルに2000年以降のデータが入っています。

id year name area prefecture
1 2000 智弁和歌山 近畿 和歌山
2 2001 日大三 関東 東京
3 2002 明徳義塾 四国 高知
19 2018 大阪桐蔭 近畿 大阪

Controller

indexが元になる画面で、listはAjaxで一覧部分を取得するためのものです。
検索はfriendsofcake/searchで行います。

/src/Controller/HighSchoolsController.php
public function index()
{
    $area = ['北海道' => '北海道', '東北' => '東北', '関東' => '関東', '中部' => '中部', '近畿' => '近畿', '中国' => '中国', '四国' => '四国', '九州' => '九州'];
    for ($i = 2000;$i <= 2018;$i++) {
        $years[$i] = $i;
    }
    $this->set(compact('area', 'years'));
}

public function list()
{
    if ($this->request->is('ajax')) {
        $this->viewBuilder()->setLayout('');
        $high_schools = $this->HighSchools
            ->find('search', ['search' => $this->request->getQueryParams()])
            ->order(['year' => 'DESC']);
        $high_schools = $this->paginate($high_schools);
        $this->set(compact('high_schools'));
    }
}

Template

index.ctpで検索部分を作ります。
jsにURLを渡しておきます。
検索ボタンはsubmitではなくただのbuttonにします。

/src/Template/HighSchools/index.ctp
<?php
    $this->Html->script('high_schools', ['block' => true]);
    $this->Html->scriptStart(['block' => true]);
    echo 'var baseUrl = "'.$this->Url->build('/high-schools', false).'";';
    $this->Html->scriptEnd();
?>
<h1>高校野球 歴代優勝校</h1>
<?= $this->Form->create(null, ['id'=>'search']) ?>
<label></label>
<?= $this->Form->select('year_from', $years, ['empty'=>true]) ?> ~ <?= $this->Form->select('year_to', $years, ['empty'=>true]) ?>
<label>地域</label>
<?= $this->Form->select('area', $area, ['empty'=>'地域を選択してください']) ?>
<?= $this->Form->button('検索', ['type'=>'button', 'id' => 'button']) ?>
<?= $this->Form->end() ?>
<div id="ajax_template"></div>

list.ctpはページネーションと一覧のみです。

/src/Template/HighSchools/list.ctp
<ul class="pagination">
    <?php
        if ($this->Paginator->hasPrev()) {
            echo $this->Paginator->prev('<');
        }
        echo $this->Paginator->numbers();
        if ($this->Paginator->hasNext()) {
            echo $this->Paginator->next('>');
        }
    ?>
</ul>
<table>
    <thead>
        <tr>
            <th></th><th>高校</th><th>地域</th><th>都道府県</th>
        </tr>
    </thead>
    <tbody>
    <?php foreach($high_schools as $high_school){ ?>
        <tr>
            <td><?= $high_school->year ?></td>
            <td><?= $high_school->name ?></td>
            <td><?= $high_school->area ?></td>
            <td><?= $high_school->prefecture ?></td>
        </tr>
    <?php } ?>
    </tbody>
</table>

Model

friendsofcake/searchで検索できるようにします。

/src/Model/Table/HighSchoolsTable.php
public function searchManager()
{
    $searchManager = $this->behaviors()->Search->searchManager();
    $searchManager
        ->add('year_from', 'Search.Compare', ['operator' => '>=', 'field' => 'year'])
        ->add('year_to', 'Search.Compare', ['operator' => '<=', 'field' => 'year'])
        ->value('area');

    return $searchManager;
}

JavaScript

そして肝心のjsです。
Ajaxでhigh-schools/listにアクセスして、戻り値としてlist.ctpの中身を受け取り、jqueryでHTMLを書き換えています。
Ajaxのurlは検索ボタンが押下されたときは入力項目のnameとvalueから作成します。
ページネーションのリンクが押下されたときはdata属性のurlから取得しています。
あらかじめページネーションのリンクは無効にして、元のhrefの値はdata属性のurlに保持しておくのがポイントです。

/webroot/js/high_schools.js
$(function(){
    // 検索ボタン押下時
    $(document).on('click', '#button', function() {
        // 検索の入力項目からurlを生成
        var url = baseUrl + '/list?';
        $('#search select').each(function(index, element) {
            if($(this).val()){
                url += $(this).attr('name') + '=' + $(this).val() + '&';
            }
        });

        searchList(url);
    });

    // ページネーションのリンク押下時
    $(document).on('click', '.pagination a', function() {
        var url = $(this).data('url');
        if(url){
            searchList(url);
        }
    });

    // 初期表示の一覧を取得するため検索ボタン押下
    $('#button').click();
});

// 一覧を取得
function searchList(url){
    $.ajax({
        url:url,
        type:'POST',
    })
    .done(function(data){
        $('#ajax_template').html(data);
        linkDisable();
    });
}

// ページネーションのリンクを無効化し、data属性のurlに遷移先を保持
function linkDisable(){
    $('.pagination a').each(function(index, element) {
        if(!$(this).data('url')){
            $(this).data('url', $(this).attr('href'));
            $(this).attr('href', '#');
        }
    });
}
5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6