質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.04%

指定したカスタムフィールドの値で絞り込み、その最新1件ずつを表示するようなループは?

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 457

jaimy

score 7

実現したいこと

wordpressですが、wp_query等を使い、次の 条件 で記事を表示したいです。

条件

カスタムフィールドnumberの値ごとに、最新1件ずつ

たとえば次のような投稿ならば、表示したいのは、「記事B」と「記事C」です。「記事A」は表示しません。

記事 投稿日 number 表示
記事A 4/1 1 ×
記事B 4/2 1
記事C 4/3 2

なぜか

なぜ「記事A」を表示しないのかというと、同じnumberの記事は最新1件しか表示しないという条件なので、numberが「1」の最新の記事として、「記事A」でなく「記事B」を表示します。

そして「記事C」はnumberが「2」ですがこれは1つしかないので表示します。

以上の条件で記事を取得する方法がわかる方がいたら、どうかご指導をお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • CHERRY

    2019/04/22 09:39

    「記事A」と「記事B」をみると 最新1件の「最新」を判断する条件は日付ではないようですが、最新と判断した条件は何でしょうか?

    キャンセル

  • jaimy

    2019/04/22 09:54

    ご指摘大変感謝いたします。逆でした。申し訳ございませんでした。

    キャンセル

  • 退会済みユーザー

    2019/04/23 19:50

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 1

checkベストアンサー

+2

残念ながら wp_posts や WP_Query で、条件に含まれる各項目から n 件ずつ取り出すという動作を簡単に実行することは難しいです。

WordPressの WP_Query で行うとしたら

  1. カスタムフィールドに含まれる値一覧の配列を用意
  2. カスタムフィールドの値を1つずつループさせて WP_Query でデータ取得

という処理を書く必要があります。

たとえば、$values にカスタムフィールドの値一覧を用意しておいて、foreach でカスタムフィールドの項目を1項目ずつ WP_Query に渡して カスタムフィールドの値ごとに1回ずつ検索する必要があります。

$values = array( '001', '002', '009', '050', '100', '999' ); // カスタムフィールドの全項目一覧

foreach( $values as $value ) {
    $args = array(
        'posts_per_page' => 1,
        'meta_key' => 'number',
        'meta_value' => $value,
        'meta_compare' => '=',
        'order' => 'DESC',
        'orderby' => 'date',
    );
    $query = new WP_Query( $args );
    if ( $query->have_posts() ) {
        echo '<ul>';
        while ( $query->have_posts() ) {
            $query->the_post();
            echo '<li>' . get_the_title() . '</li>';
        }
        echo '</ul>';
    wp_reset_postdata();
    } else {
        // no posts found
    }   
}

関数リファレンス/WP_Query 参照


もし、SQLが、書けるのであれば、

することもできます。


(追記 2019.04.23 11:25)

カスタムクエリで対応する例

まず、条件分岐タグ を使って、どのテンプレートの場合に実行するのか条件を決めます。
条件分岐タグで、使用場所を指定しない場合、全ての SQL に適用されることになります。
内容によっては、ログインできなくなったり、一切の投稿が表示されなくなったりしますので、注意してください。

詳細がわかりませんので、アーカイブのメインクエリーと仮定します。

希望する内容が取得できる SQL を考えます。

質問の内容から推測して

SELECT wp_posts.ID
FROM wp_posts
INNER JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id
INNER JOIN ( 
    SELECT wp_postmeta.meta_value as number, max(wp_posts.post_date) as max_date
    FROM   wp_posts
    INNER JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id 
    WHERE wp_postmeta.meta_key = 'number'
    GROUP BY wp_postmeta.meta_value
  ) AS j2
  ON wp_postmeta.meta_value =j2.number AND wp_posts.post_date = j2.max_date

のような感じでしょうか。

作成した SQL を WordPress の HOOK で実行できるように構築しなおして、functions.php に記載します。
INNER JOIN は posts_joinフックを、絞り込み条件がある場合の WHERE や AND は posts_whereフックを使用します。

function my_posts_join_tt184471( $join )
{
  global $wpdb;

  if( ! is_admin() && is_archive() && is_main_query() ) {
    $join .= "INNER JOIN ". $wpdb->postmeta ." ON ". $wpdb->posts .".ID = ". $wpdb->postmeta .".post_id ";

    $join .= "INNER JOIN ( ";
    $join .= "  SELECT ". $wpdb->postmeta .".meta_value as number, max(". $wpdb->posts .".post_date) as max_date ";
    $join .= "      FROM  ". $wpdb->posts;
    $join .= "      INNER JOIN ". $wpdb->postmeta ." ON ". $wpdb->posts .".id = ". $wpdb->postmeta .".post_id  ";
    $join .= "      WHERE ". $wpdb->postmeta .".meta_key = 'number' ";
    $join .= "      GROUP BY ". $wpdb->postmeta .".meta_value ";
    $join .= "    ) AS j1 ";
    $join .= "  ON ". $wpdb->postmeta .".meta_value = j1.number AND ". $wpdb->posts .".post_date = j1.max_date ";
  }

  return $join;
}

add_filter('posts_join', 'my_posts_join_tt184471' );

使用している条件分岐タグは、下記です。

  • ! is_admin()  管理画面を除く( ! で否定 )
  • is_archive()  アーカイブテンプレート
  • is_main_query()  メインクエリー

カスタムクエリの場合、表示まわりは、標準の archive.php のままで OK です。

--

参考:

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/23 15:57

    あのすみません、おすすめの「カスタムクエリ」ですが、それはどのようなものですか?このコメントの2つ前のコードではないんですよね?

    キャンセル

  • 2019/04/23 16:00 編集

    カスタムクエリの例は、コメント欄は、markdownが使えないので、回答欄の後半にに追記していますので確認してください。

    キャンセル

  • 2019/04/23 19:52 編集

    すみません!!回答欄の追記を見ていませんでした。まさかの完全コードに申し訳ない思いです。素人の理解に合わせたご説明までどうもありがとうございました。

    ---ここに別途質問を書いていましたが、話が違うので削除しました---

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる
  • トップ
  • PHPに関する質問
  • 指定したカスタムフィールドの値で絞り込み、その最新1件ずつを表示するようなループは?