以前、WordPress のフォーラムに「日毎でランダムな記事を表示したい」というような内容のトピックが上がっていたので、投稿を取得するパラメーターの orderby にシード値として日付を指定した RAND を使用する方法を提案しました。
$seed = date_i18n( 'Ymd' );
$the_query = new WP_Query( array(
'post_type' => 'post',
'posts_per_page' => 1,
'orderby' => "RAND($seed)",
) );
これは、MySQL における RAND 数学関数のシード値が同じ場合、毎回同じ値を返すことを利用したものです。
トピックとしてはこれで解決はしたのですが、投稿数(レコード数)が変わると同じシード値でも異なる値が返される場合があるため、厳密ではありませんでした。
そこで、ここでは厳密に日毎の投稿を表示する方法を紹介します。
処理としては、WordPress の Transients API を利用して、その日限定(24:00 まで有効)の値(投稿 ID の配列)をデータベースに作成する方法です。
まずは、下記コードを functions.php に追加します。
/**
* 日毎(ローカル時間 24:00 に切り替え)のランダム投稿を取得します。
*
* @param int $count
* @return array List of posts.
*/
function get_posts_daily_random( $count = 1 ) {
$transient = 'my_daily_random_posts';
$ids = get_transient( $transient );
if ( $ids === false ) {
mt_srand( strtotime( date_i18n( 'Y-m-d H:i:s' ) ) );
$ids = get_posts( array(
'fields' => 'ids',
'post_type' => 'post',
'posts_per_page' => $count,
'orderby' => 'RAND(' . mt_rand() . ')',
) );
if ( $ids ) {
$sec = strtotime( date_i18n( 'Y-m-d 24:00:00' ) ) - strtotime( date_i18n( 'Y-m-d H:i:s' ) );
set_transient( $transient, $ids, $sec );
}
}
if ( $ids !== false ) {
return get_posts( array( 'post__in' => $ids ) );
}
return array();
}
あとは、テンプレートで、get_posts_daily_random 関数を呼び出すだけです。戻り値は 投稿オブジェクトの配列(get_posts と同じ)です。
<ul>
<?php
$myposts = get_posts_daily_random();
foreach ( $myposts as $post ) : setup_postdata( $post ); ?>
<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endforeach;
wp_reset_postdata(); ?>
</ul>