Interogare meta cu valoare booleană true/false
Încerc să afișez toate proprietățile de închiriat, mai întâi cele care nu au fost închiriate, apoi cele care sunt închiriate în prezent. Există un tip de postare personalizat 'rent' cu meta post personalizat pentru prețul închiriat (_price_rented) care este o casetă de bifat (returnează fie true sau false... true dacă A FOST închiriat). Trebuie să modific interogarea pentru a afișa toate proprietățile cu proprietățile disponibile (ne-închiriate) apărând primele și apoi proprietățile închiriate.
Iată interogarea mea:
$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',
),
)
)
);
Din anumite motive această interogare arată toate proprietățile care AU fost închiriate. Când schimb valoarea din 'false' în 'true' în meta_query nu arată nicio proprietate.
Așa că m-am gândit, valoarea returnată este fie false (pentru proprietățile care SUNT închiriate) sau NULL (pentru proprietățile care NU sunt închiriate), dar nu sunt sigur cum să interoghez pentru un rezultat NULL (nu false), am adăugat un argument 'compare' la meta_query și am setat valoarea la '!=' dar nici asta nu a funcționat.
EDITARE: var_dump returnează următoarele pentru un apartament disponibil, ne-închiriat: string(0) ""
și pentru un apartament ne-disponibil, închiriat: string(1) "1"

TL;DR: Această problemă apare probabil cel mai des când un câmp boolean este creat ca opțional. O poți rezolva fie făcându-l obligatoriu, fie folosind o interogare mai complexă pentru a prelua cazul implicit.
Mai multe detalii:
Există două probleme de reprezentare a datelor aici: una este ce valori de date sunt folosite pentru a reprezenta adevărat/fals, iar cealaltă este dacă câmpul este stocat sau nu dacă are valoarea implicită (de obicei fals).
Partea 1: Am analizat SQL-ul generat de WP_Meta_Query
pentru comparațiile cu adevărat și fals și am descoperit că pentru adevărat înlocuiește cu '1' iar pentru fals cu '' (șirul gol). Deci, orice scrii în baza de date trebuie să fie în acord cu asta dacă intenționezi să faci interogări care compară cu valori adevărate și false. În special, nu vrei să scrii '0' pentru fals. Ar putea fi mai sigur să scrii și să testezi pentru 0 și 1 (și multe constructoare de formulare fac asta). Dar verifică ce se scrie în baza de date și ține cont de asta când construiești interogarea.
Partea 2: Presupunând că fals este valoarea implicită, găsirea înregistrărilor cu valoarea adevărat este ușoară:
... 'meta_key' => 'my_key', 'meta_value' => 1
(sau true)
Dar partea cealaltă este mai dificilă: poate exista o valoare falsă sau poate să nu existe nicio valoare. Acest lucru se poate întâmpla dacă valoarea a fost listată ca opțională într-un formular - atunci cât timp utilizatorul nu o setează sau o modifică explicit, ea nu va fi adăugată în baza de date. Reține că dacă folosești doar get_post_meta
va funcționa bine în acest fel: returnarea unei valori false și returnarea fără valoare vor avea același efect.
Dar când folosești WP_Query
, nu este atât de ușor. (Sau dacă este, eu încă nu am descoperit cum).
Ai două (sau poate trei) opțiuni:
Asigură-te că câmpul este întotdeauna inițializat explicit cu o valoare reală. În unele constructoare de formulare, faci asta prin a face câmpul obligatoriu și dându-i o valoare implicită. Apoi poți testa
...'meta_value' => 0
în mod fiabil.Fă două interogări, prima care testează pentru o valoare falsă și a doua care testează pentru lipsa valorii. Acestea pot fi combinate într-o singură interogare WP_Query astfel:
meta_query => array( 'relation' => 'OR', array( 'key' => 'my_key', 'value' => 0, 'compare' => '=' ), array( 'key' => 'my_key', 'compare' => 'NOT EXISTS', ), )
Aceasta probabil nu este o interogare eficientă. În funcție de mulți factori, ar putea fi mai bine să returnezi toate obiectele și să le filtrezi în propriul cod.
- Este posibil să folosești 'fără valoare' pentru a însemna fals. Pentru a face asta, ori de câte ori valoarea ar trebui setată la fals, trebuie să ștergi valoarea meta în loc să o actualizezi.
În acest caz, o singură interogare 'NOT EXISTS'
va returna în mod fiabil obiectele corecte. (Nu cred că multe constructoare de formulare sau plugin-uri acceptă acest comportament, așa că l-aș folosi doar în cod complet personalizat.)

WP_Meta_Query
este o parte "nu foarte stabilă" în nucleul WordPress și dacă nu ești foarte atent, poate fi ușor confundată și să cauzeze probleme.
Când folosești new WP_Query()
cu argumente meta_query => array()
sau perechi cheie/valoare echivalente, atunci new WP_Meta_Query()
intervine, urmat imediat de parsare.
$this->meta_query = new WP_Meta_Query();
$this->meta_query->parse_query_vars( $q );
Valori permise
Când interoghezi metadate, există opțiunea bool
. Dacă ai folosi-o, aceasta ar reveni la CHAR
, care este valoarea implicită, deoarece array-ul de valori permise este:
'NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED'
unde NUMERIC
va fi resetat la SIGNED
.
Depanare
Există numeroase filtre care pot afecta procesul de salvare a postărilor, așa că primul lucru de făcut este verificarea diferitelor valori în cadrul unei bucle:
var_dump( get_post_meta( get_the_ID(), '_price_rented', true ) );
Apoi, în funcție de valoarea returnată, va trebui să folosești SIGNED
dacă rezultatul este 0
sau 1
, sau "true"
sau "false"
dacă rezultatul este un șir de caractere. Chiar dacă este boolean, totuși aș sugera să folosești string
pentru a te asigura că trece prin $GLOBALS['wpdb']
, care poate procesa doar %s
(șir) și %d
(număr).
Note suplimentare
În timp ce actualizam intrarea din Codex pentru WP_Meta_Query
astăzi, am observat că există multe ieșiri diferite (care adaugă numeroase JOINS
inutile, discutate pe Trac aici și aici fără un singur patch integrat în nucleu). (Urmărește tichetul pentru părțile AND
aici) Ideea este că este posibil să folosești o combinație de argumente meta_*
alături de array-ul meta_query
și subarray-urile sale. Rezultatul este destul de necunoscut decât dacă îl afișezi, așa că IMO este mai bine să folosești fie una, fie cealaltă metodă de adăugare a intrărilor. Mai ales când folosești doar meta_key
, deoarece acest lucru poate rezulta într-o "interogare doar pe cheie" în unele cazuri.
Soluție
După cum s-a menționat în comentarii:
(...)
var_dump
returnează următoarele pentru un apartament disponibil, neînchiriat:string(0) ""
și pentru un apartament indisponibil, închiriat:string(1) "1"
Acum meta_query
trebuie să folosească
'meta_query' => array( 'relation' => 'OR', array(
'meta_key' => '_price_rented',
'meta_value' => '1',
'meta_compare' => '='
) );
Dacă dorești să obții "apartamentele indisponibile, închiriate" sau să folosești '!='
pentru a obține apartamentele "neînchiriate".
Notă: Valorile posibile pentru meta_compare
sunt '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN', 'NOT EXISTS', 'REGEXP', 'NOT REGEXP'
sau 'RLIKE'
. Valoarea implicită este '='
.

Am întâmpinat aceeași problemă și după o oră de căutare am găsit valorile "NOT EXISTS"
și "EXISTS"
(doar în WP >= 3.5)
.
Deci nu este nevoie să ceri o valoare meta, doar verifici dacă meta_key există:
'meta_key' => '_price_rented' ,
'meta_compare' => 'NOT EXISTS' ,
Funcționează perfect pentru mine.

return false
este înregistrat ca 0, return true
este înregistrat ca 1
Prin urmare, adăugați pur și simplu value="1"
la input-ul de tip checkbox, astfel încât să poată trimite valoarea "1" dacă este bifat și nu "on" implicit
În interogarea meta, procedați ca de obicei:
array(
'key' => 'your_key',
'value' => 'your_value',
'compare' => '='
)
