Meta query con valore booleano true/false

31 lug 2013, 18:23:12
Visualizzazioni: 33.7K
Voti: 18

Sto cercando di mostrare tutte le proprietà in affitto, prima quelle che non sono state affittate e poi quelle attualmente affittate. C'è un custom post type 'rent' con un custom post meta per il prezzo affittato (_price_rented) che è una checkbox (restituisce true o false... true se È stata affittata). Ho bisogno di modificare la query per mostrare tutte le proprietà con quelle disponibili (non affittate) che appaiono prima e poi quelle affittate.

Ecco la mia query:

$ts_properties = new WP_Query( 
    array( 
    'post_type' => 'rent', 
    'paged' => $paged, 
    'posts_per_page' => -1,
    'meta_key' => '_price_rented',
    'orderby' => 'meta_value',
    'order' => 'DESC',
    'meta_query' => array(
        array(
        'key' => '_price_rented',
        'value' => false,
        'type' => 'BOOLEAN',
        ),
    ) 
) 
);

Per qualche motivo questa query mostra tutte le proprietà che SONO state affittate. Quando cambio il valore da 'false' a 'true' nella meta_query non mostra alcuna proprietà.

Quindi, ho pensato che il valore restituito sia false (per le proprietà che SONO affittate) o NULL (per le proprietà che NON sono affittate), ma non sono sicuro di come fare una query per un risultato NULL (non false). Ho aggiunto un argomento 'compare' alla meta_query e impostato il valore su '!=' ma non ha funzionato neanche questo.

MODIFICA: var_dump restituisce quanto segue per un appartamento disponibile, non affittato: string(0) "" e per un appartamento non disponibile, affittato: string(1) "1"

11
Commenti

utilizzando i valori 1 e 0 forse?

reikyoushin reikyoushin
31 lug 2013 18:24:55

meta_query type => string . Valori possibili sono 'NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED'. Il valore predefinito è 'CHAR'.

iEmanuele iEmanuele
31 lug 2013 18:29:01

@reikyoushin: utilizzando '1' restituisce tutte le proprietà in affitto, e '0' non restituisce alcuna proprietà.

Kegan Quimby Kegan Quimby
31 lug 2013 18:29:45

@iEmanuele: cambiare questo sembra non avere alcun effetto (pensavo la stessa cosa). L'ho visto da questo articolo: http://thethemefoundry.com/blog/query-posts-wordpress-false-null-meta-value/

Kegan Quimby Kegan Quimby
31 lug 2013 18:30:44

Intendo usare 1 e 0 per i valori invece dei booleani così non hai bisogno del meta_query.. ti basta ordinare per 'meta_key' => '_price_rented','orderby' => 'meta_value', 'order' => 'ASC',

reikyoushin reikyoushin
31 lug 2013 18:37:10

Il campo _price_rented è effettivamente impostato sia per i valori true che false, o è impostato solo per true? Controlla il database per favore. Lo chiedo perché una checkbox non selezionata non viene passata attraverso POST quindi mi chiedo se il valore sia impostato in quei casi.

s_ha_dum s_ha_dum
31 lug 2013 18:45:55

Rimuovi 'meta_key' => '_price_rented' dall'array base. Potrebbe essere che WP_Meta_Query si confonda avendo entrambi. A proposito, BOOLEAN non è valido e quindi verrà reimpostato su CHAR, che è il valore predefinito. E se usi NUMERIC, prova a passare a SIGNED. Assicurati anche di fare un var_dump( get_post_meta( get_the_ID(), '_price_rented', true ) ); e aggiungi quell'output alla tua domanda. E se è "true" o "false", allora imposta value all'interno di quell'array come stringa (racchiusa tra virgolette).

kaiser kaiser
31 lug 2013 19:06:52

@s_ha_dum è impostato solo su "true" se è deselezionato, viene restituita una stringa di caratteri 0.

Kegan Quimby Kegan Quimby
31 lug 2013 19:38:08

@kaiser var_dump restituisce quanto segue per un appartamento disponibile, non affittato: string(0) "" e per un appartamento non disponibile, affittato: string(1) "1"

Kegan Quimby Kegan Quimby
31 lug 2013 19:40:04

Vedi la soluzione nella risposta.

kaiser kaiser
31 lug 2013 19:57:51

@KeganQuimby hai fatto progressi su questo?

kaiser kaiser
19 ago 2013 20:35:15
Mostra i restanti 6 commenti
Tutte le risposte alla domanda 4
0
12

TL;DR: Questo problema probabilmente si verifica soprattutto quando un campo booleano viene creato come opzionale. Puoi risolverlo rendendolo obbligatorio, oppure usando una query più complessa per recuperare il caso predefinito.

Maggiori dettagli:

Ci sono due problemi di rappresentazione dei dati qui: uno riguarda quali valori di dati vengono utilizzati per rappresentare vero/falso e l'altro riguarda se il campo viene memorizzato o meno se è il valore predefinito (solitamente falso).

Parte 1: Ho esaminato l'SQL generato da WP_Meta_Query per i confronti con vero e falso, e ho scoperto che per vero sostituisce '1' e per falso '' (stringa vuota). Quindi qualsiasi cosa tu scriva nel database deve concordare con questo se intendi eseguire query che confrontano con valori veri e falsi effettivi. In particolare, non vuoi scrivere '0' per falso. Potrebbe essere più sicuro scrivere e testare 0 e 1 invece (e molti costruttori di form lo fanno). Ma controlla cosa viene scritto nel database e tienilo a mente quando costruisci la tua query.

Parte 2: Assumendo che falso sia il valore predefinito, trovare record il cui valore è vero è semplice:

... 'meta_key' => 'my_key', 'meta_value' => 1 (o true)

Ma l'altro lato è più complesso: potrebbe esserci un valore falso, o potrebbe non esserci alcun valore. Questo può accadere se il valore era elencato come opzionale in un form - finché l'utente non lo imposta o modifica esplicitamente, non verrà aggiunto al database. Nota che se usi solo get_post_meta funzionerà bene così: restituire un valore falso e non restituire alcun valore darà lo stesso risultato.

Ma quando usi WP_Query, non è così semplice. (O se lo è, non ho ancora capito come).

Hai due (o forse tre) opzioni:

  1. Assicurati che il campo sia sempre inizializzato esplicitamente a un valore reale. In alcuni costruttori di form, lo fai rendendo il campo obbligatorio e dandogli un valore predefinito. Quindi puoi testare ...'meta_value' => 0 in modo affidabile.

  2. Esegui due query, la prima che testa per un valore falso e la seconda che testa per nessun valore. Queste possono essere combinate in una singola WP_Query così:

    meta_query => array(
       'relation' => 'OR',
        array(
            'key'     => 'my_key',
            'value'   => 0,
            'compare' => '='
        ),
        array(
            'key'     => 'my_key',
            'compare' => 'NOT EXISTS',
        ),
    )
    

Questa probabilmente non è una query efficiente. A seconda di molti fattori, potrebbe essere meglio restituire tutti gli oggetti e filtrarli nel tuo codice.

  1. È possibile utilizzare 'nessun valore' per indicare falso. Per farlo, ogni volta che il valore dovrebbe essere impostato su falso, devi eliminare il meta valore invece di aggiornarlo.

In quel caso, una singola query 'NOT EXISTS' restituirà in modo affidabile gli oggetti corretti. (Non penso che molti costruttori di form o plugin supportino questo comportamento, quindi lo userei solo in codice puramente personalizzato).

13 nov 2016 08:34:00
0

WP_Meta_Query è una parte del core di WordPress che può essere "non molto stabile" e, se non si presta molta attenzione, può facilmente confondersi e rompersi.

Quando esegui un new WP_Query() e hai argomenti come meta_query => array() o le loro controparti a coppia chiave/valore singola, allora entra in gioco new WP_Meta_Query(), seguito immediatamente dal parsing.

$this->meta_query = new WP_Meta_Query();
$this->meta_query->parse_query_vars( $q );

Valori consentiti

Quando interroghi i metadati, c'è un'opzione bool. Se la usassi, questa ricadrebbe su CHAR, che è il valore predefinito in quanto l'array di valori consentiti è:

'NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED'

dove NUMERIC verrà reimpostato su SIGNED.

Debugging

Ci sono numerosi filtri che possono influenzare il processo di salvataggio dei post, quindi la prima cosa da fare è controllare i diversi valori all'interno di un ciclo:

var_dump( get_post_meta( get_the_ID(), '_price_rented', true ) );

Poi, a seconda del valore restituito, dovrai usare SIGNED se il risultato è 0 o 1, oppure "true" o "false" se il risultato è una stringa. Se è davvero booleano, suggerirei comunque di usare string solo per assicurarsi che passi attraverso $GLOBALS['wpdb'], che può passare solo %s per le stringhe e %d per i numeri.

Note aggiuntive

Mentre aggiornavo oggi la voce del Codex per WP_Meta_Query, ho notato che ci sono molti output diversi (che aggiungono numerose quantità di JOIN non necessari, discussi su Trac qui e qui consenza una singola patch integrata nel core). (Ticket di follow-up per le parti AND qui) Il punto è che è possibile usare una combinazione di argomenti meta_* insieme all'array meta_query e ai suoi sottoarray. Il risultato è piuttosto sconosciuto a meno che non lo si esamini con un dump, quindi secondo me è meglio usare o un metodo o l'altro per aggiungere input. Soprattutto quando si usa solo meta_key, poiché in alcuni casi questo risulta in una "query solo per chiave".

Soluzione

Come sottolineato nei commenti:

(...) var_dump restituisce quanto segue per un appartamento disponibile, non affittato: string(0) "" e per un appartamento non disponibile, affittato: string(1) "1"

Ora il meta_query deve usare

'meta_query' => array( 'relation' => 'OR', array(
    'meta_key'     => '_price_rented',
    'meta_value'   => '1',
    'meta_compare' => '='
) );

Se vuoi ottenere gli "appartamenti non disponibili, affittati" oppure usa '!=' per recuperare gli appartamenti "non affittati".

Nota: I valori possibili per meta_compare sono '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN', 'NOT EXISTS', 'REGEXP', 'NOT REGEXP' o 'RLIKE'. Il valore predefinito è '='.

31 lug 2013 19:28:18
0

Ho affrontato lo stesso problema e dopo un'ora di ricerca ho trovato i valori "NOT EXISTS" e "EXISTS" (solo in WP >= 3.5). Quindi non c'è bisogno di richiedere un meta valore, basta verificare se il meta_key esiste:

'meta_key'     =>   '_price_rented'  ,
'meta_compare' =>   'NOT EXISTS'     ,

Funziona perfettamente nel mio caso.

11 dic 2013 12:58:12
0

return false viene registrato come 0, return true viene registrato come 1

Quindi, basta aggiungere value="1" al tuo input type checkbox, così può inviare il valore "1" se selezionato e non "on" come default

Nella tua meta query, fai come al solito:

array(
  'key'     => 'your_key',
  'value'   => 'your_value',
  'compare' => '='
)
11 dic 2024 19:21:38