web-dev-qa-db-ja.com

WP_Query meta_query結果日付順

放置しないでください。これはmeta_valueをどのように並べるかについての別の質問ではありません。

eventsという投稿タイプがあり、作成する各投稿には想像的にevent_dates_wpというメタフィールドがあります。これは複数の日付を受け入れ、それらをYmd形式の配列として保存します。

以下のように、2つのWP_Queryvaluesの間の日付の投稿を返すmeta_queryがあります。

$args = [
    'post_type' => 'event',
    'order' => 'ASC',
    'orderby' => 'meta_value',
    'meta_key' => 'event_dates_wp',
    'posts_per_page' => -1,
    'meta_query' => [
      [
        'key' => 'event_dates_wp',
        'type' => 'DATE',
        'value' => '20180801',
        'compare' => '>='
      ],
      [
        'key' => 'event_dates_wp',
        'type' => 'DATE',
        'value' => '20180831',
        'compare' => '<='
      ]
    ]
  ];

これはすべてうまくいき、2018年8月1日から2018年8月31日までの間にあるevent_dates_wp値を含む投稿のリストを返します。しかし、結果は「日付中心」ではなく「ポスト中心」です。自分で説明しましょう。

上記は期待通りのものですが、私がやりたいのは、8月1日から31日までの各日付の下にリストされた一致する投稿を含めて、日付をリストすることです。

例えば:

Event A contains dates [20180801, 20180802, 20180803, 20180804]
Event B contains dates [20180803, 20180804, 20180805]
Event C contains dates [20180804, 20180807]

結果は次のようになります。

20180801 // 1st Aug 2018
Event A

20180802 // 2nd Aug 2018
Event A

20180803 // 3rd Aug 2018
Event A
Event B

20180804 // 4th Aug 2018
Event A
Event B
Event C

20180805 // 5th Aug 2018
Event B

20180806 // 6th Aug 2018
[NO RESULT]

20180807 // 7th Aug 2018
Event C

20180808 // 8th Aug 2018
[NO RESULT]

20180809 // 9th Aug 2018
[NO RESULT]
...

これを行うことができる唯一の方法は、一度に1つの日付を照会してから、次の日付に照会することです。これは良い考えではありません。日付ベースのイベントを照会し、説明されているとおりにそれらをフォーマットするという、この見かけ上一般的なパターンを達成する方法はありますか?

この種の振る舞いの良い例は Barbicanイベントページ です。これは私がDrupalを使っていると信じています。確かにこのようなことをするためのWordPressの方法がなければなりませんか?

読んでくれてありがとう!

2
PUncle

私の考えは以下の通りです。

1.あなたのイベントが持っているすべてのメタ日付の配列を取得します。 MySQLクエリのDISTINCT を意味します - 重複を含まない

<?php
/*
 * From https://wordpress.stackexchange.com/a/9451/11761
 */
function get_all_possible_meta_dates( $key = 'event_dates_wp', $type = 'page', $status = 'publish' )
{

    global $wpdb;

    $result = $wpdb->get_col( $wpdb->prepare( "
        SELECT DISTINCT pm.meta_value FROM {$wpdb->postmeta} pm
        LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
        WHERE pm.meta_key = '%s'
        AND p.post_status = '%s'
        AND p.post_type   = '%s'
    ", $key, $status, $type ) );

    return $result;
}

2.event_dates_wpメタキーを持つすべての投稿をループ処理して、投稿オブジェクトを取得します。あなたはそれが一度必要です。

3.各投稿のメタをあなたが持っている可能な日付と比較してください。一致するものがあれば、それを印刷してください。

<?php
function print_posts_by_meta_dates()
{

    $args = [
        'post_type' => 'event',
        'order' => 'ASC',
        'orderby' => 'meta_value',
        'meta_key' => 'event_dates_wp',
        'posts_per_page' => -1,
    ];

    // all events having `event_dates_wp`
    $loop = new WP_Query( $args );

    // all posssible event dates
    $distinct_meta_dates = get_all_possible_meta_dates();

    foreach( $distinct_meta_dates as $event_meta_date ) {

        // date header
        echo '<h1>' . $event_meta_date . '</h1>';

        // loop through all events
        foreach( $loop->posts as $event ) {

            // get current event dates array
            $event_all_dates = get_post_meta( $event->ID, 'event_dates_wp', false );

            // compare
            if( in_array( $event_meta_date, $event_all_dates ) ) {

                // post name
                echo '<p>' . $event->post_name;

            }
        }
    }
}

4.テンプレートのprint_posts_by_meta_dates()関数を使って投稿リストを印刷します。

5.または、投稿またはページ内で使用するためのショートコードを作成してください。

add_shortcode( 'test_shortcode', 'print_posts_by_meta_dates' );

次のようなものになります。

  • 20180801
    • テストページ-1
  • 20180802
    • テストページ-1
    • テストページ2
    • テストページ3
  • 20180803
    • テストページ2
    • テストページ3

覚えておいて、カスタムフィールドをeで区切らないでください。 g。コンマ、しかしそれらを別々に追加します。

enter image description here 

1
Max Yudin