Cum pot crea un meta_query cu un array ca meta_field?
Iată argumentele pentru interogarea mea:
$args = array(
'post_type' => 'news',
'meta_query' => array(
array(
'key' => 'topics',
'value' => 'sports',
)
)
);
Acest lucru funcționează când topics
este un string, dar nu funcționează când este un array. Aș dori ca această interogare să funcționeze când topics
este de exemplu array( 'sports', 'nonprofit', etc. )
Există vreo modalitate de a construi interogări meta cu array-uri ca meta_key?

Alimentarea interogării cu o matrice de valori posibile
Dacă valoarea din baza de date este un șir de caractere și doriți să furnizați interogării mai multe valori:
$args = array(
'post_type' => 'știri',
'meta_query' => array(
array(
'key' => 'subiecte',
'value' => array ( 'sport', 'organizații nonprofit', 'comunitate' ),
'compare' => 'IN'
)
)
);
Căutarea unei valori specifice într-o matrice serializată de date
Dacă valoarea din baza de date este o matrice cu mai multe subiecte și doriți să căutați un singur subiect în cadrul acelei matrici (Rețineți că o matrice din baza de date poate fi preluată ca atare, dar este stocată în baza de date într-o formă serializată, care este tot un șir de caractere):
$args = array(
'post_type' => 'știri',
'meta_query' => array(
array(
'key' => 'subiecte',
'value' => 'sport',
'compare' => 'LIKE'
)
)
);
Utilizarea 'LIKE' ca valoare de comparație nu este o instrucțiune la fel de clară pe cât ați sperat, dar este cea mai bună opțiune disponibilă.
Pe lângă aceasta, singura altă opțiune ar fi să preluați toate articolele care au setat meta_key "subiecte" și să le parcurgeți manual sau, cu alte cuvinte, să verificați valoarea în cadrul buclei și să afișați articolele în funcție de această condiție.
ACTUALIZARE 2021
Deși încă valabil, răspunsul de mai sus are 9 ani.
Consultați și răspunsurile excelente ale lui @sMyle și @Kaji.

Pentru a completa răspunsul lui Johannes, deoarece este vorba despre un array serializat, dacă stocați ID-uri de utilizatori (cazul meu), ar putea fi necesar să gestionați situația puțin diferit.
Meta-informațiile postului erau salvate astfel:
array( "1", "23", "99");
Deci, da, sunt numere întregi, dar prin update_post_meta
erau salvate ca șiruri de caractere.
'meta_query' => array(
array(
'key' => 'my_meta_key',
'value' => serialize( strval( 1 ) ),
'compare' => 'LIKE'
)
)
Așadar, efectuați o comparație LIKE cu versiunea serializată ca șir de caractere a ceea ce căutați.
ACTUALIZARE 2022:
O problemă de care trebuie să fiți conștienți, dacă valoarea NU este salvată ca șir de caractere (ci ca întreg), și folosiți serialize( intval( $value ) )
, există riscul să se potrivească indexul în locul valorii.
De exemplu:
array( 1234, 5678 );
Este salvat astfel:
a:1:{i:0;i:1234;i:1;i:5678;}
Dacă folosiți serialize( intval( 1 ) )
în interogarea meta, veți obține o potrivire pe i:1;
care este indexul, NU valoarea, așa că fiți atenți și, dacă controlați codul, salvați întotdeauna ca șir de caractere pentru a evita potrivirea pe index.

Am dat peste acest răspuns vechi întâmplător astăzi. Îmi place completarea ta. +1

Tocmai am dat și eu peste asta, problema mea este că trebuie să obțin toate postările unde user_id nu se află în array, dar soluția de mai sus nu funcționează așa că am făcut astfel:
'meta_query' => array(
array(
'key' => 'my_meta_key',
'value' => ':' . $user_id . ';',
'compare' => 'NOT LIKE'
)
)
Pentru că atunci când sunt serializate, toate valorile sunt salvate astfel: ':value;'

Inteligent. Îmi plac soluțiile ingenioase, mai puțin convenționale. Nu mă așteptam să găsesc așa ceva în dimineața asta. Respect.

O altă îmbunătățire ușoară față de răspunsul lui @sMyles.
Am întâlnit cazuri în care ID-urile au fost stocate atât ca șiruri de caractere (de exemplu, când sunt preluate dintr-un câmp de formular) cât și ca numere întregi (e.g. update_post_meta($post_id, authorized_users', array(get_current_user_id()));
). Aceasta seamănă cu problema binecunoscută din wp_set_object_terms()
unde poți folosi ID-uri de termeni pentru a seta termenii, dar dacă nu le convertești mai întâi în numere întregi, ai aproximativ 50% șanse să creezi termeni noi cu acele numere ca nume în loc să-i asociezi.
Aceasta poate duce la stocarea lor foarte diferit într-un array serializat, așa cum se poate vedea din fragmentele de mai jos extrase din baza de date a site-ului meu de test:
a:1:{i:0;s:1:"1";} // 's' pentru 'string', de asemenea observați ghilimelele
a:1:{i:0;i:1;} // 'i' pentru 'integer', fără ghilimele
Ambele exemple de mai sus, când sunt afișate cu print_r()
, vor arăta astfel:
Array
(
[0] => 1
)
Pentru a remedia această problemă, am făcut o mică ajustare la meta_query
prin adăugarea unei relation
și a unei alte versiuni a interogării care convertește valoarea în număr întreg în loc de șir de caractere.
Iată rezultatul final:
'meta_query' => array(
'relation' => 'OR', // Indică faptul că oricare dintre următoarele este acceptabil
array(
'key' => 'bcm_enm_authorized_users',
'value' => serialize(strval(get_current_user_id())), // Salvat ca string
'compare' => 'LIKE'
),
array(
'key' => 'bcm_enm_authorized_users',
'value' => serialize(intval(get_current_user_id())), // Salvat ca integer
'compare' => 'LIKE'
),
),
EDIT: Tocmai am realizat că această metodă ar putea prezenta riscul de coliziuni cu indecșii de array, ceea ce ar putea permite cuiva acces neautorizat la materiale dacă nu se află în array, dar ID-ul lor de utilizator apare ca index. Prin urmare, deși această metodă funcționează dacă ai problema discutată, practica mai bună este să te asiguri că orice valori pe care vrei să le cauți sunt convertite în șiruri de caractere înainte de a le salva, astfel încât să poți folosi metoda lui @sMyles în loc.

Am avut o problemă similară astăzi. A trebuit să interoghez un câmp de relație ACF (Advanced Custom Fields) cu mai mulți utilizatori asociați (array).
După actualizarea câmpului prin PHP, interogarea nu a funcționat. Însă după ce l-am actualizat prin interfața ACF, interogarea a funcționat.
Problema era că codul meu PHP seta valorile de relație ca valori întregi (int), în timp ce interfața UI le seta ca valori string. Pentru a mă asigura că ambele funcționează, acum folosesc această interogare (adaptată la exemplul de aici):
$args = array(
'post_type' => 'news',
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'topics',
'value' => '1;', // funcționează pentru array de tip int
'compare' => 'LIKE'
),
array(
'key' => 'topics',
'value' => '"1"', // funcționează pentru array de tip string
'compare' => 'LIKE'
),
)
);

Aș opta pentru răspunsul lui Johannes. Totuși, doresc să îl îmbunătățesc, deoarece folosind acel meta_query, veți întâlni un caz precum acesta:
valoarea dvs. este
array('sports','movies', 'sports2');
când căutați
$args = array(
'post_type' => 'news',
'meta_query' => array(
array(
'key' => 'topics',
'value' => 'sports',
'compare' => 'LIKE'
)
)
);
atunci rezultatul va returna atât 'sport' cât și 'sport2'.
Pentru a remedia aceasta, schimbați argumentele meta_query în
$args = array(
'post_type' => 'news',
'meta_query' => array(
array(
'key' => 'topics',
'value' => 'sports";',
'compare' => 'LIKE'
)
)
);
Acest lucru se întâmplă deoarece valoarea este serializată în baza de date, iar fiecare element va fi separat prin punct și virgulă. Astfel, argumentele de mai sus vor funcționa.
Dacă elementele din valoare sunt numere, trebuie doar să eliminați ghilimelele "
$args = array(
'post_type' => 'news',
'meta_query' => array(
array(
'key' => 'topics',
'value' => '1;',
'compare' => 'LIKE'
)
)
);
