サポート » 使い方全般 » WP_Queryで「複数投稿タイプについて、それぞれX件ずつ」は可能ですか?

  • 解決済 pineapplepine

    (@pineapplepine)


    WordPress初心者です。ざっとですが、記事一覧を取得するWP_Query()を調べてみました。しかし目的の書き方がわからず、有識者のみなさまにお聞かせいただきたく存じます。宜しくお願い致します。

    さて記事一覧の取得は次の書き方によって「fruitsを3件」取得できると思います。

    $args = [
      'post_type'      => ['fruits'],
      'posts_per_page' => 3,
    ];
    $the_query = new WP_Query( $args );

    質問ですが、「fruitsを3件、vegetablesを3件」という取得をするにはどのように書けばよろしいでしょうか?

    ひょっとしたら、上のような$the_queryの生成を、fruitsとvegetablesについて1回ずつやらないといけませんでしょうか?

    ざっと調べた感じではそう思われたのですが、もし次のような書き方があればと思っています。
    もしこのsorezore-3について適切な書き方がございましたら教えていただけましたら幸いです。

    $args = [
      'post_type'      => ['fruits','vegetables'],
      'posts_per_page' => sorezore-3,
    ];
    $the_query = new WP_Query( $args );
15件の返信を表示中 - 1 - 15件目 (全15件中)
  • こんにちは

    ざっと調べた感じではそう思われたのですが、もし次のような書き方があればと思っています。

    posts_per_page で指定できる値は整数です。

    WP_Query クラスや get_posts() では難しいと思います。$wpdb->get_results() で SQL クエリを実行して取得する方がまだ簡単かなと思います。
    https://wpdocs.osdn.jp/関数リファレンス/wpdb_Class#.E4.B8.80.E8.88.AC.E7.9A.84.E3.81.AA.E7.B5.90.E6.9E.9C.E3.82.92.E8.BF.94.E3.81.99_SELECT

    参考トピック: https://ja.wordpress.org/support/topic/カスタム投稿と普通の投稿が混在の新着/

    pineapplepine

    (@pineapplepine)

    こんにちは。ご回答どうもありがとうございます。
    なるほど、直にSQLですか。頂いたリンク先をじっくり拝読し勉強して参ります。

    サンプルコードを書いてみました。

    $sql = "SELECT t1.* 
    FROM {$wpdb->posts} t1 
    WHERE 3 >= ( 
        SELECT COUNT(*) 
        FROM {$wpdb->posts} t2 
        WHERE t1.post_type = t2.post_type 
        AND t2.post_date >= t1.post_date and post_status = 'publish' 
    ) and post_type IN ('fruits', 'vegetables') and post_status = 'publish' 
    ORDER BY post_date desc";
    
    $news_posts = $wpdb->get_results( $sql );
    if ( $news_posts ) {
    	foreach ( $news_posts as $post ) {
    		setup_postdata( $post ); ?>
    		<h2><?php the_title(); ?></h2>
    	<?php }
    	wp_reset_postdata();
    }

    もう一例

    $sql = "SELECT t1.ID 
    FROM {$wpdb->posts} t1 
    WHERE 3 >= ( 
        SELECT COUNT(*) 
        FROM {$wpdb->posts} t2 
        WHERE t1.post_type = t2.post_type 
        AND t2.post_date >= t1.post_date and post_status = 'publish' 
    ) and (post_type IN ('fruits', 'vegetables') and post_status = 'publish' 
    ORDER BY post_date desc";
    
    $post_ids = $wpdb->get_results( $sql );
    $post__in = array_column( $post_ids, 'ID' );
    
    $the_query = new WP_Query( [ 'post__in' => $post__in ] );
    if ( $the_query->have_posts() ) {
    	while ( $the_query->have_posts() ) {
    		$the_query->the_post();
    		echo '<h2>' . get_the_title() . '</h2>';
    	}
    	wp_reset_postdata();
    }
    pineapplepine

    (@pineapplepine)

    おはようございます。解決済みとしたにも関わずサンプルコードを頂戴できるとは思ってもみませんでした。ありがとうございます。
    条件が多く難易度が高く感じておりましたので、大変心強いサンプルとなりそうです。ブックマークして末永く使わせて頂きます。

    pineapplepine

    (@pineapplepine)

    たびたび失礼します。もしよろしければ以下3つについてご教授願えませんでしょうか。

    【1】
    t1とt2何を意味しているのでしょうか?

    それがわからず次のあたりなどが解読できません。
    WHERE t1.post_type = t2.post_type
    AND t2.post_date >= t1.post_date
    これらはWHEREということでテーブルの場所を指定しているのだと思いますが、何が=で、何が>=なのですか?

    【2】
    上のpost_typeとpost_dateの2つは
    WHERE 3 >= ( )
    のかっこの中なのに、下の指定はかっこの外にあるのはなぜでしょうか?
    and post_type IN (‘fruits’, ‘vegetables’)
    and post_status = ‘publish’

    【3】
    oder_byはWP_Queryにある指定ですが、なぜ次のように大文字になるのでしょうか?
    ORDER BY post_date desc”;

    基本的にWP_Queryにあるものは次のようにして、【3】の並びに繋げればいい、というわけではないのでしょうか?
    and post_type IN (‘fruits’, ‘vegetables’)
    and post_status = ‘publish’
    and order_by = ‘desc’ // ←このように

    そしてこれも
    WHERE 3 >= ( )
    のかっこの外にあるのはなぜですか?

    以上の3つになります。SQLのサンプルはネットに少なく、なかなか難しいです。
    初心者の理解レベルから長文になってしまい申し訳ございませんが、どうぞ宜しくお願い致します。

    【1】
    メインクエリ(括弧の外)とサブクエリ(括弧の中)で同じテーブルを使用するので区別するためにエイリアス(t1, t2)を付けました。

    【2】
    括弧の中はサブクエリです。

    【3】
    ORDER BY などの予約語や関数は、大文字小文字を区別しません。

    SQL の基本的な書き方(エイリアスやサブクエリ)に関しては検索してみてください。

    脱線的な話題ですいません。
    その1
    「取得」の際のposts_per_pageがスレ主にとって必須な場合なのでしょうか。
    レスポンスの速さの問題が最後に残ると思いますが、「表示」するときに3回づつという選択はどうなんでしょう。

    if(果物==投稿タイプ){
     3回表示;
    }
    if(野菜==投稿タイプ){
     3回表示;
    }

    foreachとかforとかの繰り返しが必要でしょうが。
    結果として、3回づつ「表示」されるなら、手段はえらばない?
    get template partは使えるんでしょうか。
    3回づつ表示はどうコードを書けばいいのでしょう。

    その2
    fruitsとvegetablesのカスタム投稿は必要なんでしょうか。
    foodなり商品なりのカスタム投稿に、fruitsとvegetablesのカスタム分類かカスタムフィールドの方がいいのでは。カスタムフィールドとカスタム分類にそれぞれにfruitsとvegetablesがあると便利とは思うのですが、第3者で慣れてない場合、2度入力の必要があるので煩雑さが増えるのですがどうしたもんなんでしょう。

    pineapplepine

    (@pineapplepine)

    @ishitaka
    重要なワードをありがとうございます。検索してみます。

    pineapplepine

    (@pineapplepine)

    @oisit

    その1はよくわかりませんでした。すみません。

    その2はなるほどと思いました。

    カスタム投稿タイプを使っているのはfruitsとvegetablesがそれぞれ3万件くらいあるので投稿タイプを分けたほうがすっきりするのではないかという直感に従っただけでしたので、カスタム分類にしてもいいかもしれません。
    カスタム投稿タイプとカスタム分類の使いわけが慣れないとわからないものです。

    ただカスタム分類にした場合でも「それぞれ3件ずつ」と取得する見通しが立ちません。妙案あれば賜りたいです。

    説明下手なので申し訳ない。
    @pineapplepineさんがしたいことが、「スマホやPC3個づつ表示する」ならという前提。
    その場合

    1. 最初に3個づつ取得して、3個づつ画面表示する
    2. 該当するもの全部取得して、画面表示するときに3個づつ選んで表示する

    結果は一緒ではないでしょうか。
    2の場合
    取得した全オブジェクトのうち内post_typeがfruitsの場合3回とvegetablesの場合3回表示する。
    if文と繰り返し条件文使えば何とかなるのではないかなと。

    前提が成り立たなければ斜め上の口出しだったということで忘れてください。

    もう一例

    fruits と vegetables のそれぞれで3件づつ投稿を取得 (get_posts()) して、取得した投稿をマージ (array_merge()) しソート (usort()) するのが簡単かもしれません。

    $fruits_posts = get_posts( [ 'post_type' => 'fruits', 'posts_per_page' => 3 ] );
    $vegetables_posts = get_posts( [ 'post_type' => 'vegetables', 'posts_per_page' => 3 ] );
    
    // マージして日付でソート
    $mixed_posts = array_merge( $fruits_posts, $vegetables_posts );
    usort( $mixed_posts, function ( $a, $b ) { return  strtotime( $a->post_date ) > strtotime( $b->post_date ) ? -1 : 1; });
    
    foreach ( $mixed_posts as $post ) {
    	setup_postdata( $post );
    	echo '<p>' . get_the_title() . '</p>';
    }
    wp_reset_postdata();

    前提が違うんですね。
    fruits



    vegetables


    じゃなくて、ひとまとめで






    なんですね。
    失礼しました。

    前提が違うんですね。

    すみません。私の早合点です。勝手にそう解釈してしまいました。

    ひょっとしたら、上のような$the_queryの生成を、fruitsとvegetablesについて1回ずつやらないといけませんでしょうか?

    この場合1回ずつでいいかと思います。

    日付順にする必要がない場合は、サンプルコードの usort() は必要ありません。

    pineapplepine

    (@pineapplepine)

    @ishitaka
    もう一例にも感謝です。わかりやすくて助かります。

    @oisit
    いえ、前者のように3個ずつで考えていました。
    (ページネーションが必要なので、そのような取得が必要と考えています)

    お二方ありがとうございました。ひとまず最後のishitaka様のご返答のように、1回ずつということにしたいと思います。

15件の返信を表示中 - 1 - 15件目 (全15件中)
  • このトピックに返信するにはログインが必要です。