サポート » 使い方全般 » カスタム投稿で指定した時間間隔でランダム表示する

  • 解決済 fukufumi

    (@fukufumi)


    カスタム投稿にチャレンジしていますが、どうしてもやりたいことができません。
    やりたいことは、
    1、カスタム投稿の内容をランダム表示
    2、ランダム表示をブラウザのリロード毎ではなく、一日おきにランダム表示する。
    (ランダム表示したいものはtタイトルと画像です)
    3、投稿は数十件するが、表示はランダムで5件

    <?php
    $loop = new WP_Query( array( 'post_type' => 'test', 'posts_per_page' => 5, 'orderby' =>rand ) );
    while ( $loop->have_posts() ) : $loop->the_post();
    ?>
    
    <h2><?php the_title(); ?></h2>
     <p>
    <?php echo wp_get_attachment_image(get_post_meta($post->ID,"photo-test",true)); ?>
    </p>
    <?php endwhile;wp_reset_query(); ?>

    こちらのソースでランダム表示は可能になりましたが、
    F5ボタンを押す度に表示がランダムで切り替わってしまいます。
    1日の中で何度F5を押しても同じ5件が出て、1日絶つと(24時間毎、もしくは夜の0時を過ぎると)違うランダムの5件が表示される、という処理は可能でしょうか。
    ご存知の方がいらっしゃればご教示願います。

    [モデレーターによる編集: 「【重要】 お読みください」はフォーラム管理上のお知らせを掲載するカテゴリーですので質問のトピックには使用されないようお願いします。質問のトピックを作成される際には最もあてはまるカテゴリーを選択してください。本件は「使い方全般」カテゴリーに移動します。]

    [モデレーターによる編集: コードを投稿に含める際にはその部分を逆クォート(`)で囲んでください。そうしないとページのレイアウトを崩すおそれがあります。]

12件の返信を表示中 - 1 - 12件目 (全12件中)
  • orderby => rand は、MySQL の RAND() を使うのですが、そうすると、お示しのようになってしまうので、かわりに RAND(n) を渡すとよいと思います(MySQL のマニュアルをご覧ください)。

    $today = new Date();
    $seed = strtotime($today->format('Y-m-d'));

    みたいな感じで、$seed を RAND() に渡すとよいのではないでしょうか。速度が問題なら、unixtime をビット演算して、下位16ケタくらいをマスクしてもいいかもしれません。WordPress に渡すには、posts_orderbyposts_orderby_request というフィルタフックがあります。

    こんにちは

    試していませんが
    http://pear.php.net/manual/ja/package.caching.cache-lite.php

    等で、キャッシュの有効期限を1日に設定しておけば、実現できそうだと思います

    トピック投稿者 fukufumi

    (@fukufumi)

    ご回答いただきありがとうございます!
    ネットでカスタム投稿のランダム表示に関しての記事を探していますが、なかなか見つけられないので、とても助かります。

    >nobitaさん
    キャッシュ系プラグインでの処理なのですが、Quick Cacheを利用する予定で、キャッシュのクリアも必要な時は頻繁に行うようになりそうですので、キャッシュ処理は難しそうです・・・

    >kjmtshさん
    WordPressと共にPHPも勉強中でして、申し訳ございませんが後半の文章の意味すら理解できていない状態です。

    <?php
    $loop = new WP_Query( array( ‘post_type’ => ‘test’, ‘posts_per_page’ => 5, ‘orderby’ =>rand ) );
    while ( $loop->have_posts() ) : $loop->the_post();
    ?>

    このループの ‘orderby’ =>rand を
    RAND()に入れかえればいいのでしょうか?
    $seedの変数で日付を取得し、日付が変わると新しいランダム表示に切り替わるという理解でよろしいでしょうか。

    ちなみにRAND($seed) とためしてみましたが、真っ白状態です・・・

    試していませんが、

    http://wpdocs.sourceforge.jp/Transients_API

    を使ってもいいかも

    ところでこれは
    ランダムが一日維持するのはユーザーごとなのでしょうか?サイトまるごとなのでしょうか?
    ユーザー毎で24時間同じランダム順番というのならクッキーか何かで保存しておいてもいい気がします。

    トピック投稿者 fukufumi

    (@fukufumi)

    >gogowebさん
    ユーザーごとではなくサイトごとです。
    厳密にいうと、トップページと下層の新着情報一覧の2ページにランダム表示を適用したいです。

    キャッシュやクッキーで対応しまうと、ユーザー側でPCやスマホなど閲覧する端末が変わった時や、ブラウザの設定によってランダム表示が変わってしまうのは避けたいです。

    コンテンツの詳細を話せなくて申し訳ないのですが、
    例えてみると、「今日のわんこ」というコンテンツを作ったとします。
    ・毎日4匹の犬の画像とその犬の名前を表示。画像と犬の名前はカスタム投稿で追加。
    ・1日毎に4匹の犬は変わる。
    ・”今日の”わんこなので1日の間に(リロードする度に)犬が変わってはいけない。
    ・ランダムで出てくる犬は投稿日順ではなく、並び順もランダム。

    やりたいことはこんな感じです。
    なのでユーザーの見る環境が変わった場合にも1日の間は同じ内容が出て、1日経つと新しいランダム表示が反映される結果にしたいです。

    投稿のスラッグに曜日を指定してdate関数で切り替えるなどやり方は可能でしたが、これでは記事の投稿日順に出てきてしまうので(投稿日が早い記事がいつも上位にきてしまう)、やはりphpの関数などで実装したいです。

    >nobitaさん
    これは初めて知りました!
    データベースの情報の期間調整なのでしょうか・・調べてみます!

    ちょっと時間がとれなくて、遅くなっちゃいましたが、下のような感じでどうでしょうか。CURDATE() は MySQL の関数で、当日の日付を返します。PHP は使わず、全部 MySQL にやってもらう感じです。

    function myorderby($orderby) {
        return 'RAND(CURDATE())';
    }
    add_filter('posts_orderby', 'myorderby');
    $loop = new WP_Query($args);
    ...
    wp_reset_query();
    remove_filter('posts_orderby', 'myorderby');

    ページングしないなら、get_posts() を使った方がいいかもしれませんね。

    トピック投稿者 fukufumi

    (@fukufumi)

    お礼が遅くなり大変失礼しました。(ソースをいただきながらも多少苦戦していました)
    MySQLの関数を使用させていただき、無事やりたいことができました!

    <?php
    function myorderby($orderby) {
    return ‘RAND(CURDATE())’;
    }
    add_filter(‘posts_orderby’, ‘myorderby’);
    $loop = new WP_Query($args);
    ?>
    <?php query_posts( array(
    ‘post_type’ => ‘test’,
    ‘posts_per_page’ => 5
    )); ?>
    <?php if(have_posts()): ?>
    <?php while(have_posts()):the_post(); ?>
    (ループ内容)
    <?php endwhile; else: wp_reset_query(); ?>
    <?php remove_filter(‘posts_orderby’, ‘myorderby’); ?>

    で、カスタム投稿の記事を5件表示し、1日毎にランダムで切り替わる処理ができました!
    大変助かりました、ありがとうございます。

    同じページにループが2つ以上ある場合にひとつしかきかず、まだ苦戦中ですが、とりあえずやりたいことができました!
    ご丁寧にありがとうございました。

    解決済みになっていますが… 使い方を間違えています。query_posts() は捨ててください。fukufumi さんのコードでは、WP_Query で作ったオブジェクトと、query_posts() が参照しているオブジェクトは別のものになります。

    WP_Queryクラスは、一度オブジェクトを作ってしまえば、取得したデータを使いまわしたり、途中で切ったり、自在に扱えるように、クラス変数やメソッドが用意されています。何度もデータベースアクセスをする必要はありません。

    テンプレートタグなどは省略して、書きますので、適当にマークアップしてください。

    function myorderby($orderby) {
        return 'RAND(CURDATE())';
    }
    add_filter('posts_orderby', 'myorderby');
    $args = array(
        'post_type' => 'test',
        'posts_per_page' => 10, // 2箇所で使う投稿の合計数
    );
    $loop = new WP_Query($args);
    remove_filter('posts_orderby', 'myorderby');
    // 最初のループ
    if ($loop->have_posts()) {
        while ($loop->have_posts()) {
            $loop->the_posts();
            // 0 ~ 4 までの投稿処理
            if ($loop->current_post == 4) break;
        }
    }
    ...
    // 2度目のループ上と同じ投稿を使いたい場合は、次の行のコメントマークを外す
    // $loop->rewind_posts();
    if ($loop->have_posts()) {
        while ($loop->have_posts()) {
            $loop->the_post();
            // 5 ~ 最後までの投稿処理
        }
    }
    wp_reset_query();

    比較のために書きましたが、2度目以降のループは、if文がなくても動作します。後は stylesheet でどこにでも持って行ってください。

    トピック投稿者 fukufumi

    (@fukufumi)

    使い方を間違っていましたか。
    必要以上にデータベースにアクセスしていたんですね。
    改めてご指摘ありがとうございます!

    ページ内にふたつなんですが、
    home.phpとsidebar.phpに分かれており、別種類の投稿を両方ともランダム表示させようとしています。

    homeの方で普通の投稿をランダム表示し、
    サイドバーの方ではカスタム投稿で作った投稿をランダム表示するというものです。
    (ブラウザの見た目上は1ページですが、phpファイルが分かれており、投稿内容も違います)

    この場合もオブジェトはひとつと捉えて良いのでしょうか。
    おかげさまで、後一歩のところまで来ましたが、自分の不慣れのため後はその課題だけです。
    いただいたソースを元に考えてみます!

    ああ、なるほど。ここで作ったのは、サイドバーに表示するためのものだったのですね。

    普通の投稿とカスタム投稿は、データを作る条件が違いますから、使い回しはできません(可能ではあるけれども、やらない方がよい、というのが正確な表現ですが)。2つ目のループは破棄してください。

    home.php というのは、トップページだと思いますが、こちらは、pre_get_posts をキーワードに検索すると、情報が得られると思います。日付でランダムデータを切り替えるのは、たぶん見つからないと思いますので、骨格だけ補足しておきます。if の条件をきちんと設定しないと、あちこちでランダム表示になりますので注意してください(グローバルにランダムというのも、ちょっと楽しいサイトになりそうな気がしますけどね)。

    functions.php に書いてください。

    add_action('pre_get_posts', 'random_display');
    function random_display($query) {
        if (is_admin() || !$query->is_main_query()) return;
        // is_front_page は機能しません
        if ($query->is_home()) {
            $query->set('post_type', 'post');
            $query->set('posts_per_page', 10);
            // 通常のランダム表示を使いたい場合は次の行のコメントを外し、
            // 下のフックと関数を削除する
            // $query->set('orderby', 'rand');
        }
    }
    add_filter('posts_orderby', 'myorderby');
    function myorderby($orderby) {
        // ここできちんと条件を設定すること
        if (is_home()) return 'RAND(CURDATE())';
        return $orderby;
    }
    トピック投稿者 fukufumi

    (@fukufumi)

    ありがとうございます!
    function.phpに書くことで、普通の投稿とカスタム投稿の両方で1日単位のランダムができました!
    自分で考えていると泥沼にはまっていたと思います!

    kjmtshさん、何度もソースのご提供、本当にありがとうございました。
    制作する必要があるサイトで、一人ではできなかったので大変助かりました。
    WordPressの使用もだいぶ慣れてきたと思っていましたが、カスタマイズにはまだまだ勉強が必要だと実感しました。
    みなさんがご意見を出してくださったので、新たに学んだ事がたくさんありました。
    ありがとうございました。

12件の返信を表示中 - 1 - 12件目 (全12件中)
  • トピック「カスタム投稿で指定した時間間隔でランダム表示する」には新たに返信することはできません。