前回まで作った管理テーブルに対し、データ件数が増えてきた場合を想定して、ページング処理を入れます。
前回までの、テーブル一覧部分のコードは以下のとおりです。
/**
* 初期表示
*/
function disp()
{
//データ一覧
echo <<< EOL
<form action="" method="post">
<h2>データ一覧</h2>
<input type='submit' name='submit[regist]' class='button-primary' value='新規登録' />
<div class="wrap">
<table class="wp-list-table widefat striped posts">
<tr>
<th nowrap>ID</th>
<th nowrap>名前</th>
<th nowrap>登録日時</th>
<th nowrap>詳細</th>
<th nowrap>編集</th>
</tr>
EOL;
global $wpdb;
$tbl_name = $wpdb->prefix . 'sample_mst';
$sql = "SELECT * FROM {$tbl_name} ORDER BY id;";
$rows = $wpdb->get_results($sql);
foreach($rows as $row) {
echo "<tr>";
echo "<td>" . $row->id . "</td>";
echo "<td>" . $row->sample_name . "</td>";
echo "<td>" . $row->create_date . "</td>";
echo "<td>";
echo "<input type='submit' name='submit[detail][" . $row->id . "]'";
echo " class='button-primary' value='詳細' />";
echo "</td>";
echo "<td>";
echo "<input type='submit' name='submit[edit][" . $row->id . "]'";
echo " class='button-primary' value='編集' />";
echo "</td>";
echo "</tr>";
}
echo "</table>";
echo "</div>";
echo "</form>";
}
このコードに対し、ページ処理を入れていきます。
まず、現在のページ番号をGETパラメータで受け渡す為、パラメータ取得用の変数を用意し、取得します。
$pageid = filter_input(INPUT_GET, 'pageid');
次に、1ページあたり、何件表示して次のページに移るのか、上限を決定します。
//1ページあたりの件数
$limit = 10;
次に、対象となるデータの総件数を取得します
//DBオブジェクトを用意
global $wpdb;
//全件数取得
$tbl_name = $wpdb->prefix . 'sample_mst';
$sql = "SELECT count(*) AS CNT FROM {$tbl_name}";
$rows = $wpdb->get_results($sql);
$recordcount = $rows[0]->CNT;
ここで、$recordcountという変数に総件数が格納されます。
次に、ページ遷移した時に、データベースからオフセットした値を取得する為に、SQL用にoffset値を決定します。
//offsetの値を決定
$offset = $pageid * $limit;
最後に、データベースにクエリを発行し、データを取得します。
ここのタイミングではlimit件数(10件ごと)にデータを区切って取得しています。
//offset と limitによる画面表示用のデータ取得
$sql = "SELECT * FROM {$tbl_name} ORDER BY id limit {$offset}, {$limit};";
//通常の取得方法(SQL実行結果を、オブジェクトとして取得)
$rows = $wpdb->get_results($sql);
次にページ処理用のメソッドと、それに応じたパラメータを書いておきます。
$args = array(
'label' => __('Per Page'),
'default' => 10,
'option' => 'disp'
);
$page_html = self::pagination($recordcount);
paginationというメソッド名は、function disp()の外側の任意の箇所に記述します。
function pagination($recordcount)
{
$count = $recordcount;
$limit = 10;
//レコード総数がゼロのときは何も出力しない
if (0 === $count) {
return '';
}
//現在表示中のページ番号(ゼロスタート)
$intCurrentPage = self::getCurrentPage();
//ページの最大数
$intMaxpage = ceil($count / $limit);
//現在ページの前後3ページを出力
$intStartpage = (2 < $intCurrentPage) ? $intCurrentPage - 3 : 0;
$intEndpage = (($intStartpage + 7) < $intMaxpage) ? $intStartpage + 7 : $intMaxpage;
//url組み立て
$urlparams = filter_input_array(INPUT_GET);
$items = [];
//ページURLの生成
//最初
$urlparams['page'] = filter_input(INPUT_GET, 'page');
$urlparams['pageid'] = 0;
$items[] = sprintf('<span><a href="?%s">%s</a></span>'
, http_build_query($urlparams)
, '最初'
);
//表示中のページが先頭ではない時
if (0 < $intCurrentPage) {
$urlparams['pageid'] = $intCurrentPage - 1;
$items[] = sprintf('<span><a href="?%s">%s</a></span>'
, http_build_query($urlparams)
, '前へ'
);
}
for ($i = $intStartpage; $i < $intEndpage; $i++) {
$urlparams['pageid'] = $i;
$items[] = sprintf('<span%s><a href="?%s">%s</a></span>'
, ($intCurrentPage == $i) ? ' class="current"' : ''
, http_build_query($urlparams)
, $i + 1
);
}
//表示中のページが最後ではない時
if ($intCurrentPage < ($intMaxpage - 1)) {
$urlparams['pageid'] = $intCurrentPage + 1;
$items[] = sprintf('<span><a href="?%s">%s</a></span>'
, http_build_query($urlparams)
, '次へ'
);
}
//最後
$urlparams['pageid'] = $intMaxpage - 1;
$items[] = sprintf('<span><a href="?%s">%s</a></span>'
, http_build_query($urlparams)
, '最後'
);
return $items;
}
最終的に、$page_htmlという変数に、ページング出力用の情報が入るので、それを画面出力用に整形して、出力します。
//ページ部分の表示
echo "<div class='admin_pagination'>";
echo "<ul>";
foreach ($page_html as $key => $value) {
echo "<li>" . $value . "</li>";
}
echo "</ul>";
このままでは、文字列のみのページ表示になるので、cssでスタイルを調整します。
/* ページング処理 */
.admin_pagination ul li {
display: inline-block;
padding: 0px 1px 0px 1px;
margin: 0px 3px 0px 3px;
background-color: #DBDBDB;
}
.admin_pagination ul li .current a{
color: #FFFFFF;
background-color: #666666;
}
.admin_pagination ul a {
display: block;
padding: 8px 10px 8px 10px;
}
これで、テーブルに関連するページング処理の表示ができました。
出力結果は以下のようになります。
試しに3ページ目にアクセスする。
このように表示されます。
作っている最中に、気づきが遅かった部分がありました。
$wpdbのオブジェクトに対し、get_resultsメソッドを使ったSQL実行で、
offset、limitの処理を書いた場合、一般的なSQLの書き方では、
思うような抽出結果が得られませんでした。
SELECT * FROM テーブル名 OFFSET 10 LIMIT 5;
などと書くのはNGで、
SELECT * FROM テーブル名 LIMIT 10, 5;
のように書かないと、想定した出力結果が得られませんでした。
wpdbのget_resultsの仕様ページを見たのですが、明確な記載はありませんでした。
気づくまでに時間がかかってしまいました。
(2022/07/21 追記)
下記の箇所に不具合がありましたので、修正したコードに更新しました。
if文の「$intMaxpage」について、ページ遷移の仕方によっては不正な条件判定でしたので「($intMaxpage – 1)」という調整をしています。
根本的な対処とは言えませんが、訂正いたします。
■変更前
//表示中のページが最後ではない時
if ($intCurrentPage < $intMaxpage) {
$urlparams['pageid'] = $intCurrentPage + 1;
$items[] = sprintf('<span><a href="?%s">%s</a></span>'
, http_build_query($urlparams)
, '次へ'
);
}
■変更後
//表示中のページが最後ではない時
if ($intCurrentPage < ($intMaxpage - 1)) {
$urlparams['pageid'] = $intCurrentPage + 1;
$items[] = sprintf('<span><a href="?%s">%s</a></span>'
, http_build_query($urlparams)
, '次へ'
);
}
(2022/07/22 追記)
記載したソースコードの中で呼ばれているメソッド「getCurrentPage」の中身については、下記のメソッドになります。
/**
* 現在のページ番号を取得する
* @return int
*/
function getCurrentPage()
{
$pageid = esc_attr($_REQUEST["pageid"]);
return $pageid;
}