meta_query con valori meta come array serializzati

9 mag 2011, 05:06:35
Visualizzazioni: 81.7K
Voti: 51

Sto lavorando su un progetto in cui sto creando un tipo di post personalizzato e dati personalizzati inseriti tramite meta box associati al mio tipo di post personalizzato. Per qualche motivo ho deciso di codificare i meta box in modo che gli input in ciascun metabox facciano parte di un array. Per esempio, sto memorizzando longitudine e latitudine:

<p> 
    <label for="latitude">Latitudine:</label><br /> 
    <input type="text" id="latitude" name="coordinates[latitude]" class="full-width" value="" /> 
</p> 
<p>     
    <label for="longitude">Longitudine:</label><br /> 
    <input type="text" id="longitude" name="coordinates[longitude]" class="full-width" value="" /> 
</p>

Per qualche motivo, mi piaceva l'idea di avere una singola voce postmeta per ogni metabox. Nel hook save_post, salvo i dati in questo modo:

update_post_meta($post_id, '_coordinates', $_POST['coordinates']);

Ho fatto questo perché ho tre metabox e mi piace avere solo 3 valori postmeta per ogni post; tuttavia, ora ho realizzato un potenziale problema. Potrei voler utilizzare WP_Query per estrarre solo determinati post basati su questi valori meta. Per esempio, potrei voler ottenere tutti i post che hanno valori di latitudine superiori a 50. Se avessi questi dati nel database individualmente, magari usando la chiave latitude, farei qualcosa del genere:

$args = array(
    'post_type' => 'my-post-type',
    'meta_query' => array(
        array(
            'key' => 'latitude',
            'value' => '50',
            'compare' => '>'
        )
    )
 );
$query = new WP_Query( $args );

Dato che ho la latitudine come parte del postmeta _coordinates, questo non funzionerebbe.

Quindi, la mia domanda è: esiste un modo per utilizzare meta_query per interrogare un array serializzato come ho in questo scenario?

0
Tutte le risposte alla domanda 14
6
52

No, non è possibile, e potrebbe anche essere pericoloso.

Non esiste un modo affidabile per farlo senza incappare in problemi e insidie come una ricerca di 10 che corrisponde a 100 o 210, o che corrisponde al sotto-valore sbagliato, ecc. Tali soluzioni sono inaffidabili e presentano problemi di prestazioni e sicurezza.

I dati serializzati sono un vettore di attacco e un problema significativo per le prestazioni.

Affronterò:

  • Come risolvere il problema e rendere i dati interrogabili
  • Perché non puoi interrogare all'interno di dati serializzati?
    • Perché LIKE non è una soluzione
  • Una nota sull'archiviazione di record/entità/oggetti come oggetti serializzati nei meta
  • Sicurezza e oggetti serializzati
  • Cosa fare se ho una lista di ID?
  • Cosa fare se ho un array di elementi nominati?
  • Evitare completamente il problema
  • Conclusione

Ma che dire di LIKE?

Potresti vedere alcune domande ben intenzionate che suggeriscono di usare LIKE per ottenere questo risultato. Questo non risolve il problema? Questa non è la soluzione, è una falsa illusione.

Ci sono diversi problemi principali:

  • corrispondenze errate, cercare test con LIKE corrisponderà anche a test, testing, untested e altri valori
  • non c'è modo di limitare questo ai sotto-chiavi per array con chiavi o oggetti
  • non è possibile eseguire ordinamenti
  • è estremamente lento e costoso

LIKE funzionerà solo per situazioni specifiche e limitate che sono irrealistiche, e comporta una pesante penalizzazione delle prestazioni.

Risolvere il problema e rendere i dati interrogabili

Consiglio vivamente di deserializzare i dati e modificare la routine di salvataggio. Qualcosa di simile a questo dovrebbe convertire i dati nel nuovo formato:

$args = [
    'post_type' => 'my-post-type',
    'meta_key' => '_coordinates',
    'posts_per_page' => -1,
];
$query = new WP_Query( $args );
if ( $query->have_posts() ) {
    while ( $query->have_posts() ) {
        $query->the_post();
        // ottieni i dati
        $c = get_post_meta( $post->ID, '_coordinates', true );

        // salvali nel nuovo formato, post meta separati, termini di tassonomia, ecc.
        add_post_meta( $post->ID, '_longitude', $c['longitude'] );
        add_post_meta( $post->ID, '_latitude', $c['latitude'] );

        // Opzionale: pulisci i vecchi post meta
        delete_post_meta( $post->ID, '_coordinates', $c );
    }
    wp_reset_postdata();
}

Quindi potrai interrogare come desideri con chiavi individuali

Se hai bisogno di archiviare multiple longitudini e multiple latitudini, puoi archiviare multiple post meta con lo stesso nome. Basta usare il terzo parametro di get_post_meta, e restituirà tutti come un array

Perché non puoi interrogare all'interno di dati serializzati?

MySQL li vede solo come una stringa e non può suddividerli in dati strutturati. Suddividerli in dati strutturati è esattamente ciò che fa il codice sopra

Potresti essere in grado di interrogare per porzioni parziali di dati, ma questo sarà super inaffidabile, costoso, lento e molto fragile, con molti casi limite. I dati serializzati non sono pensati per query SQL e non sono formattati in modo regolare e costante.

Oltre ai costi delle ricerche parziali di stringhe, le query sui post meta sono lente, e i dati serializzati possono cambiare a seconda di cose come la lunghezza dei contenuti, rendendo la ricerca incredibilmente costosa, se non impossibile a seconda del valore che stai cercando

Una nota sull'archiviazione di record/entità/oggetti come oggetti serializzati nei meta

Potresti voler archiviare un record di transazione nei post meta, o qualche altro tipo di struttura di dati nei user meta, per poi imbatterti nel problema sopra.

La soluzione qui non è dividerli in post meta individuali, ma realizzare che non avrebbero mai dovuto essere meta fin dall'inizio, ma un custom post type. Ad esempio, un log o un record può essere un custom post type, con il post originale come genitore, o collegato tramite un termine di tassonomia

Sicurezza e oggetti serializzati

Archiviare oggetti PHP serializzati tramite la funzione serialize può essere pericoloso, il che è sfortunato dato che passare un oggetto a WordPress significa che verrà serializzato. Questo perché quando l'oggetto viene deserializzato, viene creato un oggetto e tutti i suoi metodi di risveglio e costruttori vengono eseguiti. Questo potrebbe non sembrare un grosso problema finché un utente non riesce a intrufolare un input accuratamente costruito, portando a esecuzione di codice remoto quando i dati vengono letti dal database e deserializzati da WordPress.

Questo può essere evitato usando JSON invece, il che rende anche le query più facili, ma è molto più facile/veloce semplicemente archiviare i dati correttamente ed evitare dati serializzati strutturati fin dall'inizio.

Cosa fare se ho una lista di ID?

Potresti essere tentato di dare a WP un array, o di trasformarlo in una lista separata da virgole, ma non devi farlo!

Le chiavi dei post meta non sono uniche, puoi archiviare la stessa chiave più volte, ad esempio:


$id = ...;
add_post_meta( $id, 'mylist', 1 );
add_post_meta( $id, 'mylist', 2 );
add_post_meta( $id, 'mylist', 3 );
add_post_meta( $id, 'mylist', 4 );
add_post_meta( $id, 'mylist', 5 );
add_post_meta( $id, 'mylist', 6 );

Ma come ottengo i dati indietro? Hai mai notato come le chiamate a get_post_meta hanno un terzo parametro che è sempre impostato su true? Impostalo su false:

$mylist = get_post_meta( $id, 'mylist', false );
foreach ( $mylist as $number ) {
    echo '<p>' . esc_html( $number ) . '</p>;
}

Cosa fare se ho un array di elementi nominati?

E se volessi archiviare questa struttura di dati in un modo che mi permetta di interrogare i campi?

{
  "foo": "bar",
  "fizz": "buzz"
  "parent": {
    "child": "value"
  }
}

È facile, suddividili con prefissi:

add_post_meta( $id, "tomsdata_foo", "bar" );
add_post_meta( $id, "tomsdata_fizz", "buzz" );
add_post_meta( $id, "tomsdata_parent_child", "value" );

E se hai bisogno di ciclare su alcuni di questi valori, usa get_post_meta( $id ); per prendere tutti i post meta e ciclare sulle chiavi, ad esempio:

$all_meta = get_post_meta( $id );
$look_for = 'tomsdata_parent';
foreach ( $all_meta as $key => $value ) {
    if ( substr($string, 0, strlen($look_for)) !== $look_for ) {
        continue; // non corrisponde, salta!
    }
    echo '<p>' . $key . ' = ' . $value . '</p>';
}

Che produrrà:

<p>tomsdata_parent_child = value</p>

Ricorda, quando WP recupera un post recupera tutti i suoi post meta contemporaneamente, quindi le chiamate a get_post_meta sono molto economiche e non attivano query extra al database

Evitare completamente il problema

Se sai che avrai bisogno di cercare/interrogare/filtrare su un sotto-valore, perché non archiviare un post meta aggiuntivo con quel valore così puoi cercarlo?

Conclusione

Quindi non hai bisogno di archiviare dati strutturati come una stringa nel database, e non dovresti farlo se prevedi di cercare/interrogare/filtrare su quei valori.

Potrebbe essere possibile usare un'espressione regolare e un LIKE, ma questo è estremamente inaffidabile, non funziona per la maggior parte dei tipi di dati, ed è molto, molto lento e pesante per il database. Inoltre non puoi eseguire calcoli sui risultati come potresti fare se fossero valori separati

20 ago 2012 18:19:49
Commenti

Per chi passa di qui, non smettere di leggere: risposte più utili (e recenti) si trovano più sotto

Erenor Paz Erenor Paz
13 apr 2017 13:07:01

E se ho un array di ID da salvare - e ognuno non rappresenta una chiave diversa sotto cui potrei salvarli come 'latitudine' ecc., ma c'è solo una chiave per tutti (come quando si salvano relazioni ecc.). Cosa fare in quel caso? La soluzione di @rabni?

trainoasis trainoasis
16 giu 2017 10:52:59

Puoi memorizzare una chiave più di una volta, le coppie chiave-valore non sono univoche. Per quanto riguarda le relazioni, è proprio a questo che servono le tassonomie. Se stai usando i meta per mappare più elementi su qualcosa, inseriscili invece in un termine di tassonomia

Tom J Nowell Tom J Nowell
19 giu 2017 20:31:41

Naturalmente è possibile. Sì, devi assicurarti di avere valori univoci, che è la natura stessa di tali postmeta. Solitamente, questi valori serializzati derivano da checkbox che sono array. Ogni checkbox del set dovrebbe avere un valore unico. E se non lo ha, si assicurano che la sua opzione (in php: la chiave dell'array) sia univoca, così puoi trovarla.

Successivamente, la query è un compito semplice rispetto alla soluzione che hai presentato: 'meta_query' => array( array( 'key' => 'thekey', 'value' => 'thevalue', 'compare' => 'LIKE', 'type' => 'CHAR', ), ),

User User
17 feb 2023 09:42:18

@BedaSchmid questo non fa quello che pensi, se avessi letto la mia risposta avresti visto che ho affrontato la clausola LIKE e sottolineato i principali difetti che la rendono inaffidabile e causano bug. Vedi la parte intitolata "E riguardo a LIKE?". Ho modificato la mia risposta per spostarla più in alto per le persone che non leggono l'intera risposta, dato che ce ne sono stati alcuni nel corso degli anni

Tom J Nowell Tom J Nowell
17 feb 2023 11:42:52

@TomJNowell - di quei 4 motivi, solo uno è un problema serio e come ho spiegato nel commento è evitabile. Lento? Sì. Ogni query sui meta è lenta. Ordinamento? Ok. Immagino che se hai davvero bisogno di interrogare quel campo potresti soprassedere sull'ordinamento. È comunque un po' strano ordinare per un array in cui potrebbero essere selezionate più scelte. È possibile interrogare per tali valori e non restituisce risultati inaccurati, purché l'array serializzato abbia valori univoci, come ho menzionato nel mio commento

User User
18 feb 2023 12:50:12
Mostra i restanti 1 commenti
6
41

Anch'io mi sono trovato in questa situazione. Ecco cosa ho fatto:

$args = array(
    'post_type' => 'my-post-type',
    'meta_query' => array(
        array(
            'key' => 'latitude', // Chiave meta
            'value' => sprintf(':"%s";', $value), // Formatta il valore per la ricerca serializzata
            'compare' => 'LIKE' // Operatore di confronto
        )
    )
);

Spero che questo possa aiutare

16 apr 2015 15:38:57
Commenti

Mi è piaciuta molto questa soluzione. Sfortunatamente, non è applicabile quando il $value è anche un ID. In quel caso, suggerisco di creare due funzioni: una per aggiungere un carattere a ogni elemento dell'array prima di salvare i dati e un'altra per rimuovere il carattere prima di utilizzare i dati. In questo modo, l'indice serializzato i:2 non verrà confuso con il i:D2 dei dati "reali". Il parametro della meta query dovrebbe quindi diventare 'value' => sprintf(':"D%s";', $value), e manterrai la corretta funzionalità di questa splendida risposta!

Erenor Paz Erenor Paz
13 apr 2017 12:30:09

Questa soluzione funziona per me

Rakhi Rakhi
12 gen 2018 11:32:02

Anche questo ha funzionato perfettamente per me. Ho avuto un mini attacco di panico quando ho visto la soluzione accettata però

Shane Jones Shane Jones
26 feb 2018 12:48:20

@Erenor Paz, ho appena pubblicato una soluzione che funziona bene sia con ID che con Stringhe: https://wordpress.stackexchange.com/a/299325/25264

Pablo S G Pacheco Pablo S G Pacheco
29 mar 2018 22:09:08

usare LIKE è un ottimo e veloce modo per far crashare il tuo server (per non parlare dei falsi positivi) faresti meglio ad avere una cache molto efficiente.

Mark Kaplun Mark Kaplun
2 apr 2018 08:23:41

Nota che con questa soluzione, corrisponderà a qualsiasi sotto-valore con quel valore. Quindi se cerchi una latitudine di 5, corrisponderà anche a longitudini di 5. Questo è meno problematico in questo caso particolare, ma è qualcosa da tenere a mente. È anche impossibile ordinare i risultati, e non è possibile eseguire alcuna logica/matematica come recuperare tutti i valori sopra o sotto un numero

Tom J Nowell Tom J Nowell
29 mag 2020 12:29:37
Mostra i restanti 1 commenti
0
11

Perderai davvero la capacità di interrogare i tuoi dati in modo efficiente quando serializzi le voci nel database di WordPress.

Il risparmio e il guadagno complessivo in termini di prestazioni che pensi di ottenere con la serializzazione non saranno apprezzabili in modo significativo. Potresti ottenere un database leggermente più piccolo, ma il costo delle transazioni SQL sarà elevato se dovessi interrogare quei campi e provare a confrontarli in modo utile e significativo.

Invece, riserva la serializzazione per i dati che non intendi interrogare in quel modo, ma a cui accederesti solo in modo passivo tramite la chiamata diretta all'API di WordPress get_post_meta() - da questa funzione puoi anche decomprimere una voce serializzata per accedere alle sue proprietà array.

Infatti, assegnando il valore true come in:

$meta = get_post_meta( $post->ID, 'key', true );

Restituirà i dati come un array, accessibile per essere iterato come di consueto.

Puoi concentrarti su altre ottimizzazioni del database/sito come la cache, la minificazione di CSS e JS e l'utilizzo di servizi come un CDN se necessario. Per citarne solo alcuni... WordPress Codex è un buon punto di partenza per scoprire di più su questo argomento: QUI

20 ago 2012 17:36:42
5

Penso ci siano 2 soluzioni che possono provare a risolvere il problema dei risultati memorizzati sia come Stringhe che come Interi. Tuttavia, è importante dire, come altri hanno sottolineato, che non è possibile garantire l'integrità dei risultati memorizzati come Intero, poiché questi valori sono salvati come array serializzati, l'indice e i valori sono memorizzati esattamente con lo stesso pattern. Esempio:

array(37,87);

viene memorizzato come un array serializzato, in questo modo

a:2:{i:0;i:37;i:1;i:87;}

Nota i:0 come prima posizione dell'array e i:37 come primo valore. Il pattern è lo stesso. Ma passiamo alle soluzioni


1) Soluzione REGEXP

Questa soluzione funziona per me indipendentemente dal fatto che il meta valore sia salvato come stringa o numero/id. Tuttavia utilizza REGEXP, che non è veloce quanto usare LIKE

$args = array(
    'post_type' => 'my-post-type',
    'meta_query' => array(
        array(
            'key' => 'latitude',
            'value' => '\;i\:' . $value . '\;|\"' . $value . '\";',
            'compare' => 'REGEXP'
        )
    )
);

2) Soluzione LIKE

Non sono sicuro della differenza di performance ma questa è una soluzione che usa LIKE e funziona sia per numeri che stringhe

 $args = array(
        'post_type' => 'my-post-type',
        'meta_query' => array(
            'relation' => 'OR',
            array(
                'key' => 'latitude',
                'value' => sprintf(':"%s";', $value),
                'compare' => 'LIKE'
            ),
            array(
                'key' => 'latitude',
                'value' => sprintf(';i:%d;', $value),
                'compare' => 'LIKE'
            )
        )
    );
29 mar 2018 22:07:17
Commenti

REGEXP è utile in alcune situazioni, ma se puoi usare LIKE, penso sia il metodo preferibile. Un link vecchio, ma ancora piuttosto utile, secondo me: https://thingsilearn.wordpress.com/2008/02/28/mysql-query-speed-regexp-vs-like/ :-)

Erenor Paz Erenor Paz
30 mar 2018 11:44:57

@ErenorPaz Hai ragione. LIKE è più veloce. Ma questa è una soluzione che funziona sia per stringhe che per numeri

Pablo S G Pacheco Pablo S G Pacheco
30 mar 2018 23:37:19

Sì...quindi, la risposta è (come sempre): dipende dalla situazione, se puoi usare "LIKE" è preferibile, altrimenti anche REGEXP andrà bene :-)

Erenor Paz Erenor Paz
31 mar 2018 16:10:05

@ErenorPaz, ho modificato la mia risposta aggiungendo una nuova soluzione che utilizza LIKE ma funziona sia per numeri che per stringhe. Non sono sicuro riguardo alle prestazioni perché deve confrontare i risultati usando OR

Pablo S G Pacheco Pablo S G Pacheco
1 apr 2018 22:41:09

Esattamente!!! che è quello che mi serve per ottenere lo stesso risultato...

Grazie mille!!!

kuldip Makadiya kuldip Makadiya
27 set 2018 14:23:28
0

Ho appena lavorato con campi serializzati e sono riuscito a eseguire query su di essi. Non utilizzando meta_query ma una query SQL.

global $wpdb; 

$search = serialize('latitude').serialize(50);

$query = $wpdb->prepare("SELECT `post_id`
FROM `wp_postmeta`
WHERE `post_id` IN (SELECT `ID` FROM `wp_posts` WHERE `post_type` = 'my-post-type')
AND `meta_key` = '_coordinates'
AND `meta_value` LIKE '%s'",'%'.$search.'%');

$ids = $wpdb->get_col($query);

$args = array(
    'post__in' => $ids,
    'post_type' => 'team' // aggiungo il tipo perché il default sarebbe 'post'
);

$posts = get_posts($args);

La query cerca prima i post con il post_type corrispondente, in modo da ridurre il numero di record in wp_postmeta da filtrare. Poi ho aggiunto una clausola WHERE per ridurre ulteriormente le righe filtrando su meta_key.

Gli ID finiscono ordinatamente in un array come richiesto da get_posts.

PS. È necessaria MySQL v5.6 o superiore per ottenere buone prestazioni con le subquery.

22 ago 2013 12:41:49
2

Un semplice trucco per questa situazione è utilizzare il confronto LIKE con il formato serializzato (lunghezza con tipo e valore stesso) come mostrato di seguito:

$id = 123; // id da verificare dai dati serializzati.
//(assumendo che i numeri siano memorizzati come stringa. Nel mio caso lo erano.)

$args = array(
    'post_type' => 'custom_post_type',
    'meta_query' => array(
        array(
            'key' => 'meta_key_to_check_from',
            'value' => 's:' . strlen($id) . ':"' . $id . '";',
            'compare' => 'LIKE'
        )
    )
);

$query = new WP_Query( $args );

Se si desidera cercare in una tassonomia personalizzata:

$id = 123; // id da verificare nei dati serializzati.
//(assumendo che i numeri siano memorizzati come stringa. Nel mio caso lo erano.)

$args = array(
    'hide_empty' => false, // recupera anche i termini non ancora utilizzati
    'meta_query' => array(
        array(
            'key' => 'meta_key_to_check_from',
            'value' => 's:' . strlen($id) . ':"' . $id . '";',
            'compare' => 'LIKE'
        )
    ),
    'taxonomy' => 'custom_taxonomy'
);

$terms = get_terms( $args );
15 mag 2022 16:22:19
Commenti

Direi che questo esempio risponde direttamente alla domanda ed è esattamente quello che stavo cercando.

Sharpey Sharpey
18 mag 2023 01:25:34

Questo risolve esattamente il problema, la migliore risposta qui!

rank rank
20 feb 2024 19:55:03
1

Questo esempio mi è stato davvero utile. È specifico per il plugin S2Members (che serializza i metadati dell'utente). Ma ti permette di interrogare una porzione di un array serializzato all'interno del meta_key.

Funziona utilizzando la funzione REGEXP di MySQL.

Qui trovi la fonte

Ecco il codice che interroga tutti gli utenti residenti negli Stati Uniti. L'ho facilmente modificato per interrogare uno dei miei campi di registrazione personalizzati e l'ho fatto funzionare in pochissimo tempo.

  <?php
global $wpdb;
$users = $wpdb->get_results ("SELECT `user_id` as `ID` FROM `" . $wpdb->usermeta . 
          "` WHERE `meta_key` = '" . $wpdb->prefix . "s2member_custom_fields' AND 
           `meta_value` REGEXP '.*\"country_code\";s:[0-9]+:\"US\".*'");
if (is_array ($users) && count ($users) > 0)
    {
        foreach ($users as $user)
            {
                $user = /* Ottieni ora l'oggetto Utente completo. */ new WP_User ($user->ID);
                print_r($user); /* Ottieni un elenco completo delle proprietà durante il debug. */
            }
    }
?>
12 dic 2012 20:43:48
Commenti

Grazie. Questa è stata l'unica cosa che ha funzionato quando cercavo di ottenere dati serializzati da un plugin di terze parti.

adamalexanderw adamalexanderw
25 apr 2023 12:40:45
0

Dopo aver letto un sacco di consigli su come eseguire una WP_Query filtrando per array serializzati, ecco come ho finalmente risolto: creando un array di valori separati da virgola utilizzando implode in combinazione con una query SQL personalizzata $wpdb che sfrutta FIND_IN_SET per cercare il valore richiesto nella lista separata da virgole.

(questo è simile alla risposta di Tomas, ma è un po' meno intensivo a livello di prestazioni per la query SQL)

1. In functions.php:

Nel tuo file functions.php (o ovunque tu stia configurando il meta box) nella funzione yourname_save_post() usa

update_post_meta($post->ID, 'checkboxArray', implode(",", $checkboxArray)); //aggiungendo l'implode

per creare l'array contenente i valori separati da virgola.

Dovrai anche modificare la variabile di output nella funzione di costruzione del meta box admin yourname_post_meta() in

$checkboxArray = explode(",", get_post_custom($post->ID)["checkboxArray"][0]); //aggiungendo l'explode

2. Nel file template PHP:

Test: se esegui un get_post_meta( $id ); dovresti vedere checkboxArray come un array contenente i tuoi valori separati da virgola invece di un array serializzato.

Ora, costruiamo la nostra query SQL personalizzata utilizzando $wpdb.

global $wpdb;

$search = $post->ID;

$query = "SELECT * FROM wp_posts
          WHERE FIND_IN_SET( $search, (
              SELECT wp_postmeta.meta_value FROM wp_postmeta
              WHERE wp_postmeta.meta_key = 'blogLocations'
              AND wp_postmeta.post_id = wp_posts.ID )
          )
          AND ( wp_posts.post_type = 'post' )
          AND ( wp_posts.post_status = 'publish' );";

$posts = $wpdb->get_results($query);

foreach ($posts as $post) {
    //il tuo contenuto del post qui
}

Nota il FIND_IN_SET, è qui che avviene la magia.

Ora... siccome sto usando SELECT * questo restituisce tutti i dati del post e all'interno del foreach puoi mostrare quello che vuoi da questi dati (fai un print_r($posts); se non sai cosa è incluso. Non configura "il loop" per te (preferisco così), ma può essere facilmente modificato per impostare il loop se preferisci (dai un'occhiata a setup_postdata($post); nel codex, probabilmente dovrai cambiare SELECT * per selezionare solo gli ID dei post e $wpdb->get_results al tipo corretto di $wpdb -- vedi anche il codex per $wpdb per informazioni su questo argomento).

Beh, ci è voluto un po' di impegno, ma siccome wp_query non supporta l'uso di 'compare' => 'IN' con valori serializzati o separati da virgola, questa soluzione è la tua migliore opzione!

Spero che questo aiuti qualcuno.

23 gen 2015 00:10:32
0

Se utilizzi l'operatore di confronto like nella tua meta query, dovrebbe funzionare correttamente per cercare all'interno di un array serializzato.

$wp_user_search = new WP_User_Query(array(
    'meta_query' => array(
        array(
            'key'     => 'wp_capabilities',
            'value'   => 'subscriber',
            'compare' => 'not like'
            )
        )
    )
);

risultato:

[query_where] => WHERE 1=1 AND (
  ( wp_usermeta.meta_key = 'wp_capabilities' 
  AND CAST(wp_usermeta.meta_value AS CHAR) NOT LIKE '%subscriber%' )
4 lug 2015 00:14:38
1

Se i miei metadati sono di tipo array, utilizzo questo metodo per la query tramite meta:

$args = array(
    'post_type' => 'fotobank',
    'posts_per_page' => -1,
    'meta_query' => array(
            array(
                   'key' => 'collections',
                   'value' => ':"'.$post->ID.'";',
                   'compare' => 'LIKE'
            )
     )
);
$fotos = new WP_Query($args);
7 lug 2016 09:50:49
Commenti

Ciò potrebbe portare a risultati indesiderati quando l'ID di un post ha lo stesso valore dell'ID della stringa serializzata

Erenor Paz Erenor Paz
13 apr 2017 13:05:22
0

Mi è venuta la curiosità riguardo alle risposte sopra, dove il meta_query puntava alla chiave latitude invece di _coordinates. Ho dovuto andare a testare se fosse davvero possibile nelle meta query puntare a una chiave specifica all'interno di un array serializzato. :)

Ovviamente non era così.

Quindi, nota che la chiave corretta da puntare è _coordinates invece di latitude.

$args = array(
     'post_type' => 'my-post-type',
     'meta_query' => array(
         array(
             'key' => '_coordinates',
             'value' => sprintf(':"%s";', $value),
             'compare' => 'LIKE'
         )
     )
 );

NOTE:

  1. Questo approccio rende possibile solo il targeting di corrispondenze esatte. Quindi cose come tutte le latitudini maggiori di 50 non sono possibili.

  2. Per includere corrispondenze di sottostringhe, si potrebbe usare 'value' => sprintf(':"%%%s%%";', $value),. (non testato)

6 lug 2017 14:57:01
0

Puoi racchiudere il valore con % per interrogare il valore serializzato:

$args = array(
    'post_type' => 'my-post-type',
    'meta_query' => array(
        array(
            'key' => 'latitude',
            'value' => '%' . 50 . '%',
            'compare' => '>'
        )
    )
 );
$query = new WP_Query( $args );
30 set 2023 20:09:06
3
-1

Ho la stessa domanda. Forse ti serve il parametro 'type'? Dai un'occhiata a questa domanda correlata: Query su Campi Personalizzati - Meta Value è un Array

Prova con:

    $args = array(
    'post_type' => 'my-post-type',
    'meta_query' => array(
        array(
            'key' => 'latitude',
            'value' => '50',
            'compare' => '>',
            'type' => 'numeric'
        )
    )
    );
12 mag 2011 20:44:40
Commenti

Grazie per il suggerimento, ma non è esattamente quello che sto cercando. Il problema è che il valore che cerco di abbinare fa parte di un array che è serializzato all'interno del database.

tollmanz tollmanz
13 mag 2011 06:10:57

Sì, hai ragione. Ho provato questa mattina e non ha funzionato neanche per me.

Ho lo stesso problema. Memorizzare un valore di una meta chiave come array. Inizio a pensare che non si possa fare e che invece dovrò memorizzarli come meta campi separati con lo stesso nome... e gestire correttamente l'eliminazione/aggiornamento degli stessi.

user4356 user4356
13 mag 2011 18:05:58

@user4356... è esattamente quello che farò. Speravo di ridurre il numero di righe da inserire per ogni post, ma immagino che non sia possibile.

tollmanz tollmanz
14 mag 2011 22:15:09
5
-1

Mi sono imbattuto in qualcosa di simile mentre utilizzavo il plugin Magic Fields. Questa soluzione potrebbe funzionare

$values_serialized = serialize(array('50'));
$args = array(
    'post_type' => 'my-post-type',
    'meta_query' => array(
        array(
            'key' => 'latitude',
            'value' => $values_serialized,
            'compare' => '>'
        )
    )
);
13 mag 2011 00:10:32
Commenti

Grazie per il suggerimento! Penso che questo sia il più vicino possibile, ma in realtà non funzionerà perché confrontare un array serializzato con un altro array serializzato non ha senso a meno che non stia cercando una corrispondenza esatta.

tollmanz tollmanz
13 mag 2011 06:08:22

Allora questa non dovrebbe essere contrassegnata come risposta corretta ed è irresponsabile da parte tua farlo. La risposta corretta dunque sarebbe 'No, non è possibile'

Tom J Nowell Tom J Nowell
20 ago 2012 18:14:28

Concordo, inoltre WP gestisce la serializzazione per te, serialize() non è necessario in questo caso...

Adam Adam
20 ago 2012 19:11:31

In effetti la risposta di @seth-stevenson è ottima quando si fa esattamente quello che ha detto, utilizzando il plugin "Magic Fields". Poiché quel plugin serializza automaticamente certi tipi di dati, questo è il modo migliore per fare un confronto ESATTO.

zmonteca zmonteca
9 gen 2013 07:02:53

@TomJNowell Fatto! Mi ci sono voluti solo 5 mesi ;)

tollmanz tollmanz
18 gen 2013 00:15:31