WP_Query folosind meta_query cu relation OR și orderby meta_value nu funcționează

5 mar. 2014, 19:06:05
Vizualizări: 16.7K
Voturi: 3

Mă lovesc de o problemă de câteva ore și nu reușesc să-mi găsesc eroarea. Există oare un bug cu tipul de relație 'OR' în 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 este ciudat este că dacă pun relația pe 'AND', funcționează conform așteptărilor. Dacă ambele condiții sunt adevărate, postarea va apărea. Dacă pun relația pe 'OR', toate postările apar și, din nu știu ce motiv, nici ordonarea nu funcționează corect. Chiar dacă schimb 'order' din 'ASC' în 'DESC', ordinea rezultatelor nu se schimbă.

Pentru a înțelege interogarea, iată detalii despre ce încerc să fac:

Vreau să afișez evenimente care sunt în desfășurare sau în viitor. Cele două metadate sunt data la care începe evenimentul (startDate) și data la care se termină evenimentul (endDate).

Deci, dacă data de început este mai mare sau egală (pentru a include evenimente care au loc astăzi) cu data de astăzi sau data de sfârșit este mai mare sau egală cu data de astăzi, afișează postarea.

A doua parte (cu data de sfârșit) este făcută astfel încât un eveniment în desfășurare să fie afișat, și nu pot elimina prima parte (cu data de început) pentru că dacă evenimentul durează o singură zi, clientul va introduce doar metadatele startDate.

Am exclus posibilitatea unui bug din cauza plugin-urilor deoarece am dezactivat toate plugin-urile și problema persistă.

Iată ce obțin dacă folosesc 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
2
Comentarii

Ce obții dacă folosești echo $evenements->request;?

gmazzap gmazzap
5 mar. 2014 20:43:13

Adăugat în corpul întrebării.

Fredy31 Fredy31
5 mar. 2014 20:56:59
Toate răspunsurile la întrebare 1
1

Problema este că WordPress preia toate articolele care au o cheie meta 'startDate', indiferent de valoarea meta.

Puteți înțelege asta din această parte a cererii:

...
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' )
)
...

deci dacă un articol are cheia meta 'startDate', acesta va fi returnat.

Cauza acestui comportament este argumentul 'meta_key'

...
new WP_Query( array(
    'post_type'     => 'evenements',
    'orderby'       => 'meta_value',
    'meta_key'      => 'startDate', // <-- aceasta este cauza
    ...

Totuși, dacă îl eliminați, nu veți putea ordona după o valoare meta, pentru că, uneori WordPress este... (nu știu termenul în engleză, completați singuri propoziția).

Soluția este (ar trebui să fie) să puneți prima parte a interogării meta (referitoare la data de început), ca argumente simple (nu parte din meta_query), iar a doua parte (referitoare la data de sfârșit) în interiorul tabloului 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'
     )
  )
));

Configurația dvs. este prea complexă pentru a o testa cu acuratețe, așa că încercați-o singur și anunțați-mă.

6 mar. 2014 01:47:16
Comentarii

Tocmai mi-a salvat de la o mare bătaie de cap. Meeersi!

Jody Heavener Jody Heavener
10 dec. 2014 23:29:19