web-dev-qa-db-fra.com

WP_Query utilisant meta_query avec une relation OR et orderby meta_value ne fonctionne pas

Je bats contre un bogue depuis quelques heures et n'arrive pas à trouver mon erreur. Pourrait-il y avoir un bogue avec le type de relation 'OU' dans WordPress?

$evenements = new WP_Query(array(
    'post_type'     => 'evenements',
    'orderby'       => 'meta_value',
    'meta_key'      => 'startDate',
    'order'         => 'ASC',
    'meta_query'    => array(
        'relation'  => 'OR',
        array(
            'key'       => 'startDate',
            'value'     => date('Ymd'),
            'compare'   => '>=',
        ),
        array(
            'key'       => 'endDate',
            'value'     => date('Ymd'),
            'compare'   => '>=',
        ),
    ),
));

Ce qui est bizarre, c’est que si je mets le terme "ET", il fonctionne comme prévu. Si les deux déclarations sont vraies, la publication apparaîtra. Si je mets relation avec "OU", tous les messages apparaîtront, et pour une raison quelconque, même l'ordre ne fonctionnera pas correctement. Même changer 'ordre' de 'ASC' en 'DESC' ne changera pas l'ordre d'arrivée des résultats.

Pour comprendre la requête, voici le détail de ce que j'essaie de faire:

Je veux montrer les événements en cours ou à venir. Les deux méta sont la date de début de l'événement (dateDébut) et la date de fin de l'événement (DateDate).

Donc, si la date de début est supérieure ou égale (pour obtenir si un événement se produit aujourd'hui) à aujourd'hui ou si la date de fin est supérieure ou égale à aujourd'hui, affichez la publication.

La deuxième partie (avec la date de fin) est créée de manière à afficher un événement en cours. Je ne peux pas supprimer la première partie (avec la date de début), car si l'événement ne dure qu'un jour, le client n'entre que la méta startDate. .

J'ai éliminé le bogue provenant de plugins car j'ai désactivé tous les plugins et le bogue était toujours présent.

Voici ce que je reçois si echo $evenements->request.

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts
INNER JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id
INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id)
INNER JOIN wp_postmeta AS mt2 ON (wp_posts.ID = mt2.post_id)
JOIN wp_icl_translations t
  ON wp_posts.ID = t.element_id AND t.element_type = 'post_evenements'
JOIN wp_icl_languages l ON t.language_code=l.code AND l.active=1
WHERE 1=1
AND wp_posts.post_type = 'evenements'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
AND (
 wp_postmeta.meta_key = 'startDate'
 OR ( mt1.meta_key = 'startDate' AND CAST(mt1.meta_value AS CHAR) >= '20140305' )
 OR ( mt2.meta_key = 'endDate' AND CAST(mt2.meta_value AS CHAR) >= '20140305' )
)
AND t.language_code='fr'
GROUP BY wp_posts.ID
ORDER BY wp_postmeta.meta_value ASC
LIMIT 0, 10
3
Fredy31

Le problème est que WordPress reçoit tous les articles qui ont une clé méta 'startDate', peu importe la valeur méta.

Vous pouvez comprendre que forment cette partie de la demande:

...
AND (
 wp_postmeta.meta_key = 'startDate'
 OR ( mt1.meta_key = 'startDate' AND CAST(mt1.meta_value AS CHAR) >= '20140305' )
 OR ( mt2.meta_key = 'endDate' AND CAST(mt2.meta_value AS CHAR) >= '20140305' )
)
...

ainsi, si une publication a la méta_key 'startDate', elle sera renvoyée.

Le coupable de ce comportement est l'argument 'meta_key'

...
new WP_Query( array(
    'post_type'     => 'evenements',
    'orderby'       => 'meta_value',
    'meta_key'      => 'startDate', // <-- this is the culprit
    ...

Cependant, si vous le supprimez, vous ne pourrez pas commander avec une méta-valeur, car parfois WordPress est ... (je ne connais pas le terme anglais, complétez la phrase vous-même).

La solution est (devrait être) mettre la première partie de votre méta requête (en ce qui concerne la date de début), en tant que plain arguments (ne faisant pas partie de meta_query), et la deuxième partie (en ce qui concerne la date de fin) dans le tableau meta_query:

$evenements = new WP_Query(array(
  'post_type'      => 'evenements',
  'meta_key'       => 'startDate',
  'meta_value'     => date('Ymd'),
  'meta_type'      => 'NUMERIC',
  'meta_compare'   => '>=',
  'orderby'        => 'meta_value',
  'order'          => 'ASC',
  'meta_query'     => array(
    'relation'  => 'OR',
     array (
       'key'     => 'endDate',
       'value'   => date('Ymd'),
       'compare' => '>=',
       'type'    => 'NUMERIC'
     )
  )
));

Votre configuration est trop complexe pour me permettre de la tester avec précision. Essayez-la vous-même et faites-la savoir.

5
gmazzap