Bootstrap 4 に対応した Smarty 3 用のページャープラグイン

以前に Bootstrap 3 用のプラグインを作成したのですが、Bootstrap 4 用に書き直してみました。

まずは、プラグイン本体( function.paging.php )。Smarty のプラグインディレクトリに保存してください。

<?php
function smarty_function_paging($params, $smarty)
{
    $total_page     = ceil($params['paging_data']['total_row_count'] / $params['paging_data']['page_row_count']);
    $total_page_str = $total_page;
    if (empty($params['paging_data']['current_page'])) {
        $params['paging_data']['current_page'] = 1;
    }

    $result = null;

    // ページが2ページ以上ある場合にページャーを表示
    if ($total_page > 1) {
        $prev     = $params['paging_data']['current_page'] - 1;
        $prev_str = $prev;
        $next     = $params['paging_data']['current_page'] + 1;
        $next_str = $next;

        $result = '<nav aria-label="Page navigation">'."\n";
        $result .= '<ul class="pagination">'."\n";

        if ($prev < 1) {
            // 最初のページ
            $result .= '<li class="page-item disabled"><span class="page-link"><span aria-hidden="true">«</span></span></li>'."\n";
            // 前のページ
            $result .= '<li class="page-item disabled"><span class="page-link"><span aria-hidden="true"><</span></span></li>'."\n";
        } else {
            // 最初のページ
            $result .= '<li class="page-item"><a class="page-link" href="'.str_replace('%p', '1',
                    $params['paging_data']['url']).'" aria-label="First"><span aria-hidden="true">«</span></a></li>'."\n";
            // 前のページ
            $result .= '<li class="page-item"><a class="page-link" href="'.str_replace('%p', $prev_str,
                    $params['paging_data']['url']).'" aria-label="Previous"><span aria-hidden="true"><</span></a></li>'."\n";
        }

        $start_page = max(1, $params['paging_data']['current_page'] - 3);
        $end_page   = min($total_page, $params['paging_data']['current_page'] + 3);

        for ($page = $start_page; $page <= $end_page; $page++) {
            $page_str = $page;

            if ($page == $params['paging_data']['current_page']) {
                // 現在のページ
                $result .= '<li class="page-item active" aria-current="page"><span class="page-link">'.$page_str.'<span class="visually-hidden">(current)</span></span></li>
'."\n";
            } else {
                $result .= '<li class="page-item"><a class="page-link" href="'.str_replace('%p', $page_str,
                        $params['paging_data']['url']).'">'.$page_str.'</a></li>'."\n";
            }
        }

        if ($next > $total_page) {
            // 次のページ
            $result .= '<li class="page-item disabled"><span class="page-link"><span aria-hidden="true">></span></span></li>'."\n";
            // 最後のページ
            $result .= '<li class="page-item disabled"><span class="page-link"><span aria-hidden="true">»</span></span></li>'."\n";
        } else {
            // 次のページ
            $result .= '<li class="page-item"><a class="page-link" href="'.str_replace('%p', $next_str,
                    $params['paging_data']['url']).'" aria-label="Next"><span aria-hidden="true">></span></a></li>'."\n";
            // 最後のページ
            $result .= '<li class="page-item"><a class="page-link" href="'.str_replace('%p', $total_page_str,
                    $params['paging_data']['url']).'" aria-label="Last"><span aria-hidden="true">»</span></a></li>'."\n";
        }
        $result .= '</ul>'."\n";
        $result .= '</nav>'."\n";
    }

    if ($params['debug']) {
        $result .= '<div class="bd-callout bd-callout-info"><h4>ページングデバッグ</h4>'."\n";
        $result .= '<ul class="list-group">'."\n";
        $result .= '<li class="list-group-item">全ページ数:'.$total_page.'</li>';
        $result .= '<li class="list-group-item">URL:'.$params['paging_data']['url'].'</li>';
        $result .= '<li class="list-group-item">ページ内表示件数:'.$params['paging_data']['total_row_count'].'</li>';
        $result .= '<li class="list-group-item">件数:'.$params['paging_data']['page_row_count'].'</li></ul></div>';
    }

    $smarty->assign('pager', $result);
}

次に呼び出し側のPHPですが、こちらは

<?php
$smarty = new Smarty();

$page = (int)filter_input(INPUT_GET, 'page');
if ($page == 0) {
    $page = 1;
}

// データベースから取得したデータが $data として
$paging_data = array(
    'page_row_count'  => 30,
    'current_page'    => $page,
    'url'             => $_SERVER['SCRIPT_NAME'].'?page=%p',
    'total_row_count' => $data->count()
);

$smarty->assign('paging_data', $paging_data);
$smarty->display('page.tpl');

みたいな感じで。%p の部分が実際にはページ番号に置き換えられます。

最後にテンプレートファイルですが

{paging paging_data=$paging_data}

でプラグインを呼び出して、ページャーを入れたいところに

{$pager}

を入れる感じです。

ちなみに

{paging paging_data=$paging_data debug=1}

とすると、プラグインに渡した値が確認できます。

基本的に Bootstrap 4 のみで表示できるようになっていますが、デバッグモードの部分だけ

.bd-callout {
  padding:1.25rem;
  margin: 1.25rem 0;
  border:1px solid #e9ecef;
  border-left-width:.25rem;
  border-radius:.25rem
}

.bd-callout h4 {
  margin-bottom:.25rem
}
.bd-callout p:last-child {
  margin-bottom:0
}
.bd-callout code {
  border-radius:.25rem
}
.bd-callout+.bd-callout {
  margin-top:-.25rem
}
.bd-callout-info {
  border-left-color:#5bc0de
}

を CSS に追加してください。Bootstrap の公式サイトでも使われているデザインなのですが、Bootstrap の CSS には定義されていないので。

この記事を書いた人

グッドネイバー

“ Webに悩むお客さまの「よき隣人」でありたい ” をモットーに、Web システム開発(主に Laravel)、Web マーケティング支援の仕事をしています。詳しい業務内容はこちら。お仕事のご依頼・ご相談はこちらからお気軽にどうぞ。