Come posso creare una meta_query con un array come meta_field?

15 giu 2012, 16:04:59
Visualizzazioni: 85.6K
Voti: 31

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?

2
Commenti

Per favore chiarisci -- intendi che il valore memorizzato di "topics" è un array? O che il valore memorizzato è una stringa, e vuoi passare più termini alla query in un array?

MathSmath MathSmath
15 giu 2012 17:03:29

@MathSmath, intendo che il valore memorizzato è un array.

mike23 mike23
15 giu 2012 17:08:13
Tutte le risposte alla domanda 5
0
58

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.

15 giu 2012 17:27:20
5
28

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.

6 giu 2015 06:09:33
Commenti

serialize(strval(1)) ha risolto il mio problema, grazie

Behzad Behzad
10 gen 2016 22:45:58

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

Johannes Pille Johannes Pille
20 ott 2016 09:07:04

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

Bobz Bobz
19 mar 2018 06:29:15

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

Johannes Pille Johannes Pille
16 ago 2020 11:30:35

Wow, mi hai salvato la giornata!

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

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.

13 lug 2018 05:44:28
Commenti

Questa dovrebbe essere la risposta selezionata, la più affidabile

Amin Abdolrezapoor Amin Abdolrezapoor
23 ott 2019 19:26:15

Sì, hai assolutamente ragione (riguardo alla tua modifica), e figurati ho accidentalmente fatto la stessa cosa nel mio codice salvando come intero invece che come stringa, quindi salva sempre come stringa (ho aggiunto una modifica anche nella mia risposta)

sMyles sMyles
25 feb 2022 00:07:01
0

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

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