Cum pot crea un meta_query cu un array ca meta_field?

15 iun. 2012, 16:04:59
Vizualizări: 85.6K
Voturi: 31

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?

2
Comentarii

Te rog să clarifici—te referi că valoarea stocată a "topics" este un array? Sau că valoarea stocată este un string și vrei să transmiți mai mulți termeni către interogare într-un array?

MathSmath MathSmath
15 iun. 2012 17:03:29

@MathSmath, mă refer că valoarea stocată este un array.

mike23 mike23
15 iun. 2012 17:08:13
Toate răspunsurile la întrebare 5
0
58

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.

15 iun. 2012 17:27:20
5
28

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.

6 iun. 2015 06:09:33
Comentarii

serialize(strval(1)) a rezolvat problema mea, Mulțumesc

Behzad Behzad
10 ian. 2016 22:45:58

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

Johannes Pille Johannes Pille
20 oct. 2016 09:07:04

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;'

Bobz Bobz
19 mar. 2018 06:29:15

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.

Johannes Pille Johannes Pille
16 aug. 2020 11:30:35

Uau, asta mi-a salvat ziua!

Akshay K Nair Akshay K Nair
17 mai 2022 09:20:31
2
10

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.

13 iul. 2018 05:44:28
Comentarii

Acesta ar trebui să fie răspunsul selectat, cel mai fiabil

Amin Abdolrezapoor Amin Abdolrezapoor
23 oct. 2019 19:26:15

Da, ai perfectă dreptate (referitor la editarea ta), și uite cum stau lucrurile am făcut și eu din greșeală asta în propriul cod, salvând ca integer în loc de string, așa că întotdeauna salvează ca string (am adăugat și eu o editare în răspunsul meu)

sMyles sMyles
25 feb. 2022 00:07:01
0

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'
        ),
    )
);
6 iul. 2018 09:22:29
0

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'
            )
        )
    );
2 nov. 2016 10:22:00