• 解決済 developer

    (@6flat)


    投稿をランダムに表示する方法でよくあるものは、ページを読み込むたびに表示内容が変わるものしか見たことがありません。
    それとは別に、誰から見ても同じ表示内容で、尚且つ読み込むたびにではなく日付変更で切り替わる、いわゆる日替わりのような形にすることはできないでしょうか?

15件の返信を表示中 - 1 - 15件目 (全18件中)
  • モデレーター gatespace

    (@gatespace)

    http://codex.wordpress.org/Transients_API
    http://www.warna.info/archives/1681/
    Transients APIを使って、24時間だけランダムで選ばれた結果を保持しておくとか。

    トピック投稿者 developer

    (@6flat)

    ありがとうございます。
    こんなAPIがあったのですね。
    データのリフレッシュは秒数指定ではなく日付変更を境にしたいのでそれができるのかが不明ですが、一先ずリンク先を見ながら手を加えてみようと思います。

    こんばんは、横から失礼します。

    データのリフレッシュは秒数指定ではなく日付変更を境にしたい

    キャッシュ生成の時の時間と日付の変わる時間とのタイムスタンプの差分から、その日に保存しておく秒数を取得できそうですね。

    $current_time = time(); // 現在のタイムスタンプ
    $refresh_time = mktime( 23, 59, 59 ); // 同日 23:59:59 のタイムスタンプ
    $cache_limit  = $refresh_time - $current_time; // 23:59:59 までの秒数
    トピック投稿者 developer

    (@6flat)

    ちょっとした工夫で対応出来るのですね。
    ありがとうございます。
    ちなみに、確認した時に時差分のずれが生じたので次の様に修正しました。

    $current_time = time() + 32400; // 現在のタイムスタンプ
    $refresh_time = mktime( 23, 59, 59 ); // 同日 23:59:59 のタイムスタンプ
    $cache_limit  = $refresh_time - $current_time; // 23:59:59 までの秒数

    これを元に進めてみようと思います。

    トピック投稿者 developer

    (@6flat)

    まだ日付変更時の確認をしていませんが、とりあえず以下の様な形でランダムに表示させる事が出来ました。
    キャッシュの生成も正常に出来ているとは思うのですが、あまり自信がないのでおかしなところがあったら指摘して頂けると助かります。

    <ul>
    <?php
    // 現在のタイムスタンプ
    $current_time = time() + 32400;
    // 同日 23:59:59 のタイムスタンプ
    $refresh_time = mktime( 23, 59, 59 );
    // 23:59:59 までの秒数
    $cache_limit  = $refresh_time - $current_time;
    $args = array( 'posts_per_page' => '10', 'orderby' => 'rand' );
    $random_daily_posts = get_transient( 'random_daily_posts' );
    if ( $random_daily_posts === false ) {
    $random_daily_posts = get_posts( $args );
    set_transient( 'random_daily_posts', $random_daily_posts, $cache_limit );
    }
    foreach ( $random_daily_posts as $post ) {
        setup_postdata( $post );
        echo '<li><a href="' . esc_attr( get_permalink() ) . '">' . esc_html( get_the_title() ) . '</a></li>' . "\n";
    }
    wp_reset_postdata();
    ?>
    </ul>

    こんにちは、

    新規に投稿した場合や、投稿を編集した時に、変更は更新できますか?

    トピック投稿者 developer

    (@6flat)

    こんにちは。
    投稿の編集・新規の投稿・新規の予約投稿はいずれも問題なく更新されました。
    更新の際にキャッシュされた投稿の一覧が変わってしまう様な事も無いみたいです。

    追記
    投稿の方には更新が確認されましたが、キャッシュされた一覧には更新した内容が反映されていませんでした。
    キャッシュされているので当然かもしれませんが、出来ればキャッシュ側にも更新を反映させられると良いですね…。

    更新の際にキャッシュされた内容が変わってしまう様な事も無いみたいです。

    そのほうがよかったんですね。余計なこと言ってしまいました

    トピック投稿者 developer

    (@6flat)

    書き込みに気付かずに追記してしまいました。
    キャッシュを削除せずに反映させられる方法があるのでしょうか?

    投稿オブジェクトそのものをキャッシュするのではなく、投稿IDのみを取り出した配列を作ってキャッシュしておけば良さそうです。

    それから、 time() の時間差の件、失礼しました。WordPress 内部で時刻を扱うタイムゾーンが UTC なので、現地時間は date_i18n( 'U' ) で取り出すのがシンプルなようです。

    $random_daily_post_ids = get_transient( 'random_daily_post_ids' );
    
    if ( false === $random_daily_post_ids ) {
        $transient_expiration  = mktime( 23, 59, 59 ) - date_i18n( 'U' );
        $random_daily_posts    = get_posts( array( 'posts_per_page' => 10, 'orderby' => 'rand' ) );
        $random_daily_post_ids = array_map( function($p){ return $p->ID; }, $random_daily_posts );
        set_transient( 'random_daily_post_ids', $random_daily_post_ids, $transient_expiration );
    }
    
    if ( !empty( $random_daily_post_ids ) ) {
        echo '<ul>' . "\n";
        foreach ( $random_daily_post_ids as $post_id ) {
            $post = get_post( $post_id );
            if ( $post ) {
                setup_postdata( $post );
                echo '<li><a href="' . esc_attr( get_permalink() ) . '">' . esc_html( get_the_title() ) . '</a></li>' . "\n";
            }
        }
        echo '</ul>' . "\n";
    }

    それから、ピックアップした投稿を日付順に表示する(というか、してもよい)場合は、ループを更にシンプルにできますね。

    if ( !empty( $random_daily_post_ids ) ) {
        $random_daily_posts = get_posts( array( 'include' => $random_daily_post_ids, 'posts_per_page' => -1 ) );
        if ( !empty( $random_daily_posts ) ) {
            echo '<ul>' . "\n";
            foreach ( $random_daily_posts as $post ) {
                setup_postdata( $post );
                echo '<li><a href="' . esc_attr( get_permalink() ) . '">' . esc_html( get_the_title() ) . '</a></li>' . "\n";
            }
            echo '</ul>' . "\n";
            wp_reset_postdata();
        }
    }

    こんな感じでいかがでしょうか。

    トピック投稿者 developer

    (@6flat)

    これ以上ないくらい求めた通りのもので、コード自体もすごく勉強になります。
    日付順の方も参考にさせて頂きます。
    ありがとうございます。
    gatespaceさんとnobitaさんも、ありがとうございました。

    トピック投稿者 developer

    (@6flat)

    解決したと思ったのですが、日付が変わってから確認したところ「日付変更までの秒数」が正確に取得できていませんでした。

    $transient_expiration  = mktime( 23, 59, 59 ) - date_i18n( 'U' );
    var_dump( $transient_expiration );

    現時刻(1:10)で値が-4200となってしまいます。
    Instant WordPressによるローカル環境ではマイナスにはならない(それでも計算は合わない)ので、多分サーバーの設定によるものだと思うのですが…。

    追記

    $transient_expiration  = 86400 - date_i18n( 'U' ) % 86400;
    var_dump( $transient_expiration );

    これで正確な残り時間を取れました。

    ※この投稿は何度も修正してます。

    何度もすみません、分かりました。色々と混乱してしまいました。

    そもそも WordPress 上ではタイムゾーンが UTC に設定されているので、一番初めのやり方で良かったんです。time() で取得した現在の時刻も、mktime( 23, 59, 59 ) で作成したキャッシュ期限の時刻も、いずれも UTC 時刻になるので、date() 等で確認した時に時差があっても当然なのでした。実際の時間と時差は出てしまいますが、今回キャッシュにあたって必要なのは現地時間ではなく、あくまでタイムゾーンが揃った2つの時刻の差分の秒数であり、UTC時刻であるこの2つから、差分は正しく取得できるんです。

    $transient_expiration = mktime( 23, 59, 59 ) - time();

    で、あとは、時差分の秒数を調整してやればいいわけです。

    $gmt_offset_seconds = get_option( 'gmt_offset' ) * 3600;

    こんな感じでしょうか。

    ああああ、これも違いますね、明日の宿題として寝ます。
    根本的に何かを勘違いしているようです。お騒がせしてすみません。
    解決されているようですので、そのままにしておいてください。

    トピック投稿者 developer

    (@6flat)

    お付き合い下さり感謝します。
    私もかなり混乱しましたが、先のコードを含めた次のいくつかのコードで取得出来ました。
    提示して頂いていたコードも、恐らく私の環境が悪かったのだと思いますが、今確認したところ正常に取得できていました。

    // ローカル環境でのテスト
    
    /*
     * 1. サーバーのタイムゾーンに関わらずUTC+9を元に今日の残り時間を取得
     * 実行速度(1000回試行): 0.0034(秒)
     */
    $transient_expiration = mktime( 24, 0, 0 ) - time() - 32400;
    
    /*
     * 2. サーバーのタイムゾーンを元に今日の残り時間を取得
     * 実行速度(1000回試行): 0.10443(秒)
     */
    $transient_expiration = mktime( 24, 0, 0 ) - date_i18n( 'U' );
    
    /*
     * 3. 関数date_i18nで取得したUNIX時間の通計秒を元に計算
     * 実行速度(1000回試行): 0.10393(秒)
     */
    $transient_expiration = 86400 - date_i18n( 'U' ) % 86400;
    
    /*
     * 4. 3.の関数date_i18nを関数timeに変更して対応
     * 実行速度(1000回試行): 0.00022(秒)
     */
    $transient_expiration = 86400 - ( time() + 32400 ) % 86400;

    一番分かりやすいのは2.なのですが、無難なのは4.なのかなと思います。

15件の返信を表示中 - 1 - 15件目 (全18件中)
  • トピック「日替わりで投稿をランダムに表示」には新たに返信することはできません。