一筋縄ではいかない ランダム×ページング
例えば、記事一覧ページに対し、投稿をランダムな並び順にしたい場合、クエリ ('orderby' => 'rand'
)を使って以下のような処理を指定するのが一般的です。
$args = [
・・・
'orderby' => 'rand' // 記事をランダムに表示させる条件
];
$query = new WP_Query( $args );
ただしここで、ランダム表示した一覧ページをページングしたい場合、上記の処理記述だけでは「1ページ目で表示した投稿が2ページ目以降にも表示されてしまう」ため、思うようなページング処理にはなりません。
では、意図したページングを行うにはどうすれば良いのか。解説していきます!
ランダム表示の仕組み
まずは、ランダム表示の仕組みです。
パラメータに'orderby' => 'rand'
を指定した場合、発行されるSQLは「ORDER BY RAND()」になります。
MySQLの「RAND()」
MySQLの「RAND()」は、「0 <= v < 1.0」の範囲内でランダムな乱数(浮動小数点値)を取得することができます。
「RAND([a])」のように引数aを指定した場合は、引数=シード値となります。同じシード値を指定した場合、同じ乱数が生成されます。
SELECT RAND();
引数を指定した時と、指定ないときでどのような乱数が取得されるのか、実際にSQLを実行してみましょう。以下は、データベースで「SELECT RAND();」を指定して実行した結果です。
指定したSQL文 | 取得結果 |
SELECT RAND(); | 0.7316800874952972 |
SELECT RAND(); | 0.11936303518653199 |
SELECT RAND(1); | 0.40540353712197724 |
SELECT RAND(1); | 0.40540353712197724 |
上記のように、引数を指定しない場合は異なる結果が返却され、同じ引数「1」を指定した場合は同じ結果が返却されているのが分かります。この取得結果の値を基にしてランダムな並び順が決定されます。
つまり、ページネーションを利用しても重複させずに表示するには、「RAND()」に引数となるシード値を指定してあげれば良いということになります。
posts_orderby を利用する
「RAND()」に引数となるシード値として、「posts_orderby」を指定します。
「posts_orderby」とは、データベースから投稿を取得する際に使用される、SQLクエリのORDER BY句を変更できるフィルターフックです。これを利用して、生成されるSQLを書き換えていきます。
参考:posts_orderby (wordpress.org)
ランダム表示をカスタマイズする関数
以下のように、functions.phpにランダム表示をカスタマイズする関数を記述していきます。
/*-----------------------------------------------
ランダム表示のカスタマイズ関数
-----------------------------------------------*/
function rand_change($orderby, $query) {
if ($query->get('orderby') === 'rand') {
// DBを操作できるグローバル変数呼び出し
global $wpdb;
// シード値の設定
// シード値が設定されている場合、その値を使用する(同じシード値を使うと同じランダム結果が得られる)
$seed = isset($_SESSION['seed']) ? $_SESSION['seed'] : '';
if (empty($seed)) {
// 正の整数を返却
$seed = rand();
$_SESSION['seed'] = $seed;
}
// SQLクエリを生成
// RAND()の引数に設定したシード値を設定
$orderby = $wpdb->prepare('RAND(%d)', $seed);
}
// 変更された並びを返却
return $orderby;
}
add_filter('posts_orderby', 'rand_change', 10, 2);
PHPの「rand()」は、ランダムな整数を返却します。その値をセッションに保持し、SQLの「RAND()」のシード値として設定することで、セッションに値が保持されている間はランダムでも同一の結果が返却されることになります。
これによって、ページが切り替わっても重複した投稿は表示されず、意図したページング機能を実装することができます!
おわりに
以上、ランダム表示でページング機能を利用したい場合は、ぜひ参考にしてみてください!
また、以下の記事では、WordPressにてページネーションを実装する方法「3つ」として、詳しく解説しています。こちらもぜひ参考にしてみてください。