Come posso creare una meta_query con un array come meta_field?
Ecco gli argomenti per la mia query:
$args = array(
'post_type' => 'news',
'meta_query' => array(
array(
'key' => 'topics',
'value' => 'sports',
)
)
);
Questo funziona quando topics
è una stringa, ma non quando è un array. Vorrei che questa query funzionasse quando topics
è per esempio array( 'sports', 'nonprofit', ecc. )
Esiste un modo per costruire meta query con array come meta_key?

Passare un array di valori possibili alla query
Se il valore nel database è una stringa e vuoi passare alla query diversi valori:
$args = array(
'post_type' => 'news',
'meta_query' => array(
array(
'key' => 'topics',
'value' => array ( 'sports', 'nonprofit', 'community' ),
'compare' => 'IN'
)
)
);
Cercare un valore specifico in un array serializzato di dati
Se il valore nel database è un array di diversi argomenti e vuoi cercare un singolo argomento all'interno di quell'array (Nota che un array nel database può essere recuperato come tale, ma risiede nel database in forma serializzata, che è comunque una stringa):
$args = array(
'post_type' => 'news',
'meta_query' => array(
array(
'key' => 'topics',
'value' => 'sports',
'compare' => 'LIKE'
)
)
);
Usare 'LIKE' come valore di compare non è un'istruzione così diretta come potresti sperare, ma è l'opzione migliore disponibile.
Oltre a questo, l'unica altra opzione sarebbe recuperare tutti i post che hanno impostato la meta_key "topics" e iterarli manualmente o, in altre parole, verificare il valore all'interno del loop e mostrare i post in base a quella condizione.
AGGIORNAMENTO 2021
Sebbene ancora valida, la risposta sopra ha 9 anni.
Dai un'occhiata anche alle eccellenti risposte di @sMyle e di @Kaji.

Per continuare sulla risposta di Johannes, dato che si tratta di un array serializzato, se per caso stai memorizzando qualcosa come ID utente (che era il mio caso), potresti doverlo gestire in modo leggermente diverso.
I meta dei post venivano salvati così:
array( "1", "23", "99");
Quindi sì, sono numeri interi ma tramite update_post_meta
venivano salvati come stringhe.
'meta_query' => array(
array(
'key' => 'my_meta_key',
'value' => serialize( strval( 1 ) ),
'compare' => 'LIKE'
)
)
Quindi in realtà stai facendo un confronto LIKE con la versione serializzata in stringa di ciò che stai cercando.
AGGIORNAMENTO 2022:
Un problema da tenere a mente quando si fa questo, se NON è una stringa quella salvata (salvata come intero), e usi serialize( intval( $value ) )
, potresti incappare nel problema di fare corrispondenza con l'indice invece che con il valore.
Per esempio:
array( 1234, 5678 );
Viene salvato così:
a:1:{i:0;i:1234;i:1;i:5678;}
Se usi serialize( intval( 1 ) )
nella meta query, otterrai una corrispondenza con i:1;
che è l'indice, NON il valore, quindi fai attenzione e se hai il controllo del codice, salva sempre come stringa per non fare corrispondenza con l'indice.

Mi sono imbattuto in questa vecchia risposta per caso oggi. Mi piace il tuo contributo. +1

Mi sono appena imbattuto anche in questo, il mio problema è che ho bisogno di ottenere tutti i post dove user_id non è nell'array, ma la soluzione sopra non funziona quindi l'ho modificata così:
'meta_query' => array(
array(
'key' => 'my_meta_key',
'value' => ':' . $user_id . ';',
'compare' => 'NOT LIKE'
)
)
Perché quando serializzati tutti i valori vengono salvati così: ':valore;'

Intelligente. Apprezzo gli approcci originali, non proprio convenzionali. Non mi aspettavo esattamente di trovarli qui stamattina. Complimenti.

Un altro piccolo miglioramento rispetto alla risposta di @sMyles.
Mi è capitato di avere casi in cui gli ID erano memorizzati sia come stringhe (ad esempio quando presi da un input di un form) che come interi (es. update_post_meta($post_id, authorized_users', array(get_current_user_id()));
). Questo è un po' come il noto problema con wp_set_object_terms()
dove puoi usare gli ID dei termini per impostarli, ma se non li converti prima in interi hai circa il 50% di probabilità di creare nuovi termini con quei numeri come nomi.
Questo può portare a una memorizzazione molto diversa in un array serializzato, come si può vedere dagli estratti di un caso simile dal database del mio sito di test:
a:1:{i:0;s:1:"1";} // 's' per 'stringa', nota anche le virgolette doppie
a:1:{i:0;i:1;} // 'i' per 'intero', nessuna virgoletta
Entrambi i precedenti, se passati attraverso print_r()
, verranno visualizzati come
Array
(
[0] => 1
)
Per risolvere questo problema, ho apportato una piccola modifica al meta_query
aggiungendo una relation
e un'altra versione della query che converte il valore in intero invece che in stringa.
Ecco il risultato finale:
'meta_query' => array(
'relation' => 'OR', // Indica che è accettabile uno dei due casi seguenti
array(
'key' => 'bcm_enm_authorized_users',
'value' => serialize(strval(get_current_user_id())), // Salvato come stringa
'compare' => 'LIKE'
),
array(
'key' => 'bcm_enm_authorized_users',
'value' => serialize(intval(get_current_user_id())), // Salvato come intero
'compare' => 'LIKE'
),
),
MODIFICA: Mi sono appena reso conto che questo metodo potrebbe rischiare collisioni con gli indici degli array, il che potrebbe consentire a qualcuno di accedere illecitamente a materiali se non sono nell'array, ma il loro ID utente appare come indice. Pertanto, anche se questo funziona se hai il problema discusso, la pratica migliore è assicurarsi che tutti i valori che vuoi cercare siano convertiti in stringhe prima di salvarli, in modo da poter usare il metodo di @sMyles.

Questa dovrebbe essere la risposta selezionata, la più affidabile

Ho avuto un problema simile oggi. Dovevo interrogare un campo di relazione ACF (Advanced Custom Fields) con più utenti correlati (array).
Dopo aver aggiornato il campo tramite PHP, la query non funzionava. Dopo averlo aggiornato tramite l'interfaccia utente di ACF, invece, la query ha funzionato.
Il problema era che il mio codice PHP impostava i valori della relazione come interi, mentre l'interfaccia utente li impostava come stringhe. Per assicurarmi che entrambi funzionassero, ora uso questa query (adattata all'esempio qui):
$args = array(
'post_type' => 'news',
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'topics',
'value' => '1;', // funziona per array di interi
'compare' => 'LIKE'
),
array(
'key' => 'topics',
'value' => '"1"', // funziona per array di stringhe
'compare' => 'LIKE'
),
)
);

Opterei per la risposta di Johannes. Tuttavia, voglio migliorarla perché utilizzando quel meta_query, potresti incontrare un caso come questo
il tuo valore è
array('sports','movies', 'sports2');
quando effettui la ricerca
$args = array(
'post_type' => 'news',
'meta_query' => array(
array(
'key' => 'topics',
'value' => 'sports',
'compare' => 'LIKE'
)
)
);
il risultato includerà sia 'sport' che 'sport2'.
Per risolvere questo problema, modifica gli argomenti del meta_query in
$args = array(
'post_type' => 'news',
'meta_query' => array(
array(
'key' => 'topics',
'value' => 'sports";',
'compare' => 'LIKE'
)
)
);
Questo perché il valore è serializzato nel database, e ogni elemento è separato da un punto e virgola. Quindi, gli argomenti sopra indicati funzioneranno
Se gli elementi nel valore sono numerici, devi semplicemente rimuovere le virgolette "
$args = array(
'post_type' => 'news',
'meta_query' => array(
array(
'key' => 'topics',
'value' => '1;',
'compare' => 'LIKE'
)
)
);
