WordPressで並び順をランダムにした際にページネーションを利用したい
WordPressのクエリーで並び順をランダム(rand)にした際にページネーションを利用をする方法を紹介します。
通常WordPressのランダムでページネーションを利用すると1ページに含まれていた投稿のいくつかが2ページ目にも含まれてしまい意図しているページネーションになりません。
これを解決するために、1ページ目に表示した投稿IDを「post__not_in」で除外することもできます。この場合、1ページ目から2ページ目へ進む際は簡単ですが、2ページ目から1ページ目に戻る際、3ページ目に進む際などページが大きくなるほど除外条件がかなり複雑になってしまいます。
そこで今回紹介する方法を利用して正しくページネーションが機能するように設定します。
ランダムを指定したときのSQL
まず、並び順をランダムにしたときのSQL文について確認しておきます。自身で確認したい場合は「posts_orderby」フックの内容を出力すると確認できます。
下記のように並び順をランダムにする場合、発行されるSQLは「ORDER BY RAND()」となります。
$args = ['orderby' => 'rand'];$query = new WP_Query( $args );
MySQLのRAND()
「RAND()」は0~1の浮動小数点をを返す関数です。この関数は引数に整数値をとることができます。引数を指定した場合、その引数をシード値として利用されます。使う上での意味合いとしては、毎度ランダムな値が生成されるのではなく、特定の値を返してくれるという感じです。文面では分かりづらいので下記の結果を見てください。
引数に「2」を指定したときは同じ値が返されているのがわかります。
SELECT RAND();/*+--------------------+| RAND() |+--------------------+| 0.7603858325261491 |+--------------------+1 row in set (0.00 sec)*/SELECT RAND(2);/*+--------------------+| RAND(2) |+--------------------+| 0.6555866465490187 |+--------------------+1 row in set (0.00 sec)*/SELECT RAND();/*+--------------------+| RAND() |+--------------------+| 0.5142016918530703 |+--------------------+1 row in set (0.00 sec)*/SELECT RAND(2);/*+--------------------+| RAND(2) |+--------------------+| 0.6555866465490187 |+--------------------+1 row in set (0.00 sec)*/
この値を基にして並び順が決定されます。ページネーション利用しても重複した結果が表示されず意図した結果を表示するには、WordPressでRANDに引数を指定してあげれば良いということになります。
WordPressでRANDに引数を指定する
WordPressでRANDに引数を指定するためには、「posts_orderby」フックを利用して生成されるSQLを書き換えてあげる必要があります。
session_start();add_filter( 'posts_orderby', function ( $orderby, $query ) {if ( $query->get( 'orderby' ) === 'rand' ) {global $wpdb;$seed = isset( $_SESSION['seed'] ) ? $_SESSION['seed'] : '';if ( empty( $seed ) ) {$seed = rand();$_SESSION['seed'] = $seed;}$orderby = $wpdb->prepare( 'RAND(%d)', $seed );}return $orderby;}, 10, 2 );
セッションで生成した値を保持し、RANDに値を指定しています。セッションが保持している間はランダムでも同一の結果を返すことができます。
rand()はphpの関数で、ランダムな正の整数を生成します。
まとめ
ランダムに表示したいというケースって意外とありますよね。そして1ページに表示するには多すぎるということも。そんなとき調べていたらこういう手法があるということを知りました。
並び順が複数ある場合にRANDを使用している場合でも正しく機能します。