Utilizarea condițiilor OR în meta_query pentru argumentul query_posts
Am căutat peste tot dar nu am reușit să găsesc nimic relevant.
Încerc să filtrez niște rezultate și când creez un array de argumente ca acesta și îl transmit către query_posts am observat că SQL-ul generat folosește AND în loc de OR pentru valoarea 'class_1_days'. Aș dori să transform asta într-un OR. Cum aș putea face acest lucru? (Folosesc LIKE deoarece datele sunt serializate, altfel aș fi încercat un "IN" și aș fi transmis un array. Care este modalitatea corectă de a face acest lucru?)
$args = array(
'taxonomy' => 'courses',
'term' => 'drawing',
'post_type' => 'school',
'paged' => $paged,
'meta_query' =>
#$checkbox_array,
array(
array(
'key' => 'instructor',
'value' => '1128',
'compare' => 'LIKE',
),
array(
'key' => 'class_1_days',
'value' => 'Vineri',
'compare' => 'LIKE',
),
array(
'key' => 'class_1_days',
'value' => 'Sâmbătă',
'compare' => 'LIKE',
),
)
);
Acesta este SQL-ul relevant care este generat unde am observat AND-ul
[138] => Array
(
[0] => SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) 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) WHERE 1=1 AND ( wp_term_relationships.term_taxonomy_id IN (18) ) AND wp_posts.post_type = 'school' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') AND ( (wp_postmeta.meta_key = 'instructor' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%1128%')
AND (mt1.meta_key = 'class_1_days' AND CAST(mt1.meta_value AS CHAR) LIKE '%Vineri%')
AND (mt2.meta_key = 'class_1_days' AND CAST(mt2.meta_value AS CHAR) LIKE '%Sâmbătă%') ) GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 0, 5

Folosește 'relation' => 'OR'
ca în exemplul din Codex de mai jos:
$args = array(
'post_type' => 'product',
'meta_query' => array(
'relation' => 'OR', /* <-- aici */
array(
'key' => 'color',
'value' => 'blue',
'compare' => 'NOT LIKE'
),
array(
'key' => 'price',
'value' => array( 20, 100 ),
'type' => 'numeric',
'compare' => 'BETWEEN'
)
)
);
$query = new WP_Query( $args );
Aceasta va genera o condiție OR
între toate blocurile meta_query. Dacă ai nevoie de ceva de genul WHERE "instructor" = 1128 AND (class_1_days = "value1" OR class_1_days = "value2")
, atunci ceva de genul acesta ar funcționa dacă datele tale nu ar fi serializate.
$args = array(
'taxonomy' => 'courses',
'term' => 'drawing',
'post_type' => 'school',
'paged' => $paged,
'meta_query' =>
array(
array(
'key' => 'instructor',
'value' => '1128',
'compare' => 'LIKE',
),
array(
'key' => 'class_1_days',
'value' => array('Friday','Saturday')
'compare' => 'IN',
)
)
);
Având în vedere că ai date serializate, acest lucru va fi dificil. Ai putea scrie un filtru pentru posts_where
, dar mă aștept ca rezultatul să fie ineficient și predispus la erori.
Abordarea corectă pentru cazuri de genul acesta, în care trebuie să cauți/filtrezi/sortezi după o anumită informație, este, în experiența mea, să nu stochezi datele ca un array serializat în primul rând. Aceasta este pur și simplu abordarea greșită dacă ai nevoie de astfel de interogări.
Dacă aș prelua acest proiect, aș parcurge datele care trebuie interogate în acest fel și aș salva fiecare parte ca o pereche cheie/valoare. Părțile pe care nu le interoghezi pot rămâne serializate. Nu există nicio modalitate (bună) de a face acest lucru în MySQL cu funcții MySQL, fie ca parte a interogării pe care o încerci, fie ca o interogare separată. Am văzut încercări de a crea o funcție MySQL "unserialize", dar nu văd rostul. Reserializarea datelor este soluția corectă.
Ar trebui să fie o interogare destul de simplă pentru a obține toate datele class_1_days
. Apoi parcurge-le și salvează părțile de care ai nevoie pentru interogare ca chei independente și pune restul înapoi ca date serializate.

Mulțumesc mult pentru răspuns. Există o modalitate prin care pot face un AND sau OR? Încerc să păstrez partea de instructor. Exemplul tău le face pe toate OR. Am nevoie doar ca partea class_1_days să fie un OR. Similar cu dacă aș avea 'value' => array(bla,bla,bla), 'compare' => IN
Practic unde Instructor = 'bla' ȘI value IN (bla,bla,bla)

Mulțumesc @S_ha_dam. Există o modalitate prin care pot deserializa baza de date. Acesta este un proiect pe care l-am preluat, așa că nu știu exact ce efect va avea. Am văzut un link către o aplicație care făcea exact asta, dar linkul era stricat.

Mulțumesc, dar simpla re-salvare nu va funcționa - acesta este un mediu live unde aceste date sunt salvate constant, iar class_1_data este doar o parte din ecuație. Există multiple elemente: class_0_data, class_2_data, etc., și acestea sunt adăugate de utilizatori. Cred că cea mai bună abordare ar fi să mă întorc și să găsesc o modalitate de a reinstala modulul și să-l configurez astfel încât să nu salveze serializat (dacă reușesc să aflu cum) și să merg mai departe X-( ... Nu am menționat partea cu celelalte clase pentru că am crezut că o să pot să o rezolv singur.

Cu siguranță va trebui să refactorizezi funcția "save", dar va fi necesar să salvezi din nou și datele existente, altfel vei ajunge cu un amestec ciudat între serializate și neserializate. Obține codul funcțional pe un server de dezvoltare, apoi pune cel live în modul de întreținere pentru douăzeci de minute într-un moment al zilei cu trafic scăzut.

Oh da, cu siguranță va trebui să modific datele curente!
asta e nasol. Credeam că va fi o soluție ușoară, vai!

stai...dar ce zici de asta...există vreo modalitate să adaug DUPĂ acest filtru încă un filtru după instructor?
Sau chiar să obțin înapoi array-ul php direct pe care îl folosește WordPress și să-l editez?

Nu sunt sigur că am înțeles ultima întrebare, dar prin filtre poți modifica interogarea să fie aproape orice dorești. Prin "atașarea" a ceva, însă, cred că nu vei ajunge la o interogare eficientă.

Uh, de exemplu, în PHP ai avea array-ul tău real ca fiind classes[1][bla], classes[2][bla] etc. Dacă aș ști cum se numește acel array, aș putea face o căutare în array și regex și să-l filtrez singur după ce am obținut rezultatele dorite din instrucțiunea OR pe care ai furnizat-o mai devreme.

Conform WordPress codex, tablourile imbricate pot fi utilizate pentru a construi interogări complexe. În exemplul tău ai nevoie de ceva de genul:
$args = array(
'taxonomy' => 'courses',
'term' => 'drawing',
'post_type' => 'school',
'paged' => $paged,
'meta_query' =>
array(
'relation' => 'AND', // relație implicită
array(
'key' => 'instructor',
'value' => '1128',
'compare' => 'LIKE', // comparare cu LIKE
),
array(
'relation' => 'OR',
array(
'key' => 'class_1_days',
'value' => 'Friday', // Vineri
'compare' => 'LIKE',
),
array(
'key' => 'class_1_days',
'value' => 'Saturday', // Sâmbătă
'compare' => 'LIKE',
),
)
)
);

A trebuit să caut asta. Am o interogare complexă care se referă la acest lucru. Ai primit atât de multe voturi încât cred că voi pune o nouă întrebare pe baza acesteia. Sunt foarte interesat să văd cum abordează comunitatea acest tip de problemă în prezent, să fiu sincer.
