web-dev-qa-db-fra.com

WP_Query meta_query résultats date par date

Ne pars pas! Ce n'est pas une autre question sur la façon de commanderby meta_value!

J'ai un type de message appelé events et chaque message que je crée a un champ méta que j'ai appelé de manière imaginative event_dates_wp qui accepte plusieurs dates et les enregistre sous la forme d'un tableau au format Ymd.

J'ai un WP_Query qui retourne les posts avec une date entre les deux meta_queryvalues, comme ceci:

$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' => '<='
      ]
    ]
  ];

Tout cela fonctionne à merveille et renvoie une liste d'articles contenant une valeur event_dates_wp comprise entre le 1er août 2018 et le 31 août 2018; mais les résultats sont plutôt "post centriques" que "centrés sur la date" - laissez-moi m'expliquer:

Ce qui précède correspond à ce à quoi on pourrait s’attendre, mais ce que je veux faire, c’est lister les dates, du 1 er août au 31, avec chaque message correspondant répertorié sous chaque date, ce qui leur permet de se répéter.

Par exemple:

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

Les résultats ressemblent à quelque chose comme:

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]
...

La seule façon pour moi de faire cela serait d'interroger une date à la fois, puis de passer à la suivante; ce qui ne peut pas être une bonne idée. Existe-t-il un moyen de réaliser ce schéma apparemment commun consistant à interroger des événements basés sur la date et à les formater comme décrit?

Un bon exemple de ce type de comportement est la page des événements Barbican , qui, je crois, utilise Drupal. Il doit sûrement y avoir un moyen WordPress de faire ce genre de chose?

Merci d'avoir lu!

2
PUncle

Mon idée suit.

1. Récupère le tableau de toutes les méta dates de vos événements. DISTINCT dans la requête MySQL signifie n'inclut pas les doublons.

<?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. Parcourez tous les messages ayant la clé méta event_dates_wp et obtenez l'objet posts. Vous en avez besoin une fois.

3. Comparez chaque publication meta aux dates possibles que vous avez. S'il y a correspondance, imprimez-la.

<?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. Imprimez la liste des publications en utilisant la fonction print_posts_by_meta_dates() dans un modèle.

5. Ou créez le shortcode à utiliser dans le message ou la page.

add_shortcode( 'test_shortcode', 'print_posts_by_meta_dates' );

Vous obtiendrez quelque chose de similaire à:

  • 20180801
    • test-page-1
  • 20180802
    • test-page-1
    • test-page-2
    • test-page-3
  • 20180803
    • test-page-2
    • test-page-3

Rappelez-vous, ne séparez pas les champs personnalisés avec e. g. virgule, mais ajoutez-les séparément:

 enter image description here 

1
Max Yudin