Interogare meta cu valoare booleană true/false

31 iul. 2013, 18:23:12
Vizualizări: 33.7K
Voturi: 18

Î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"

11
Comentarii

utilizând valorile 1 și 0 poate?

reikyoushin reikyoushin
31 iul. 2013 18:24:55

meta_query type => string. Valori posibile sunt 'NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED'. Valoarea implicită este 'CHAR'.

iEmanuele iEmanuele
31 iul. 2013 18:29:01

@reikyoushin: folosind '1' returnează toate proprietățile închiriate, iar '0' nu returnează nicio proprietate.

Kegan Quimby Kegan Quimby
31 iul. 2013 18:29:45

@iEmanuele: schimbarea acestui lucru pare să nu aibă niciun efect (am crezut și eu același lucru). Am văzut asta din acest articol: http://thethemefoundry.com/blog/query-posts-wordpress-false-null-meta-value/

Kegan Quimby Kegan Quimby
31 iul. 2013 18:30:44

Adică să folosești 1 și 0 pentru valori în loc de boolean, atunci nu ai nevoie de meta_query.. ai nevoie doar să le sortezi după 'meta_key' => '_price_rented','orderby' => 'meta_value', 'order' => 'ASC',

reikyoushin reikyoushin
31 iul. 2013 18:37:10

Este _price_rented setat efectiv atât pentru valori true cât și false, sau este setat doar pentru true? Verifică te rog în baza de date. Am întrebat pentru că o căsuță de bifat neselectată nu este trimisă deloc prin POST, așa că mă întreb dacă valoarea este setată deloc în acele cazuri.

s_ha_dum s_ha_dum
31 iul. 2013 18:45:55

Elimină 'meta_key' => '_price_rented' din array-ul de bază. S-ar putea ca WP_Meta_Query să fie confuz din cauza prezenței ambelor. Apropo, BOOLEAN nu este valid și, prin urmare, va fi resetat la CHAR, care este valoarea implicită. Și dacă folosești NUMERIC, încearcă să schimbi în SIGNED. De asemenea, asigură-te că faci un var_dump( get_post_meta( get_the_ID(), '_price_rented', true ) ); și adaugă acel output la întrebarea ta. Și dacă este "true" sau "false", atunci setează value în interiorul acelui array ca un string (înconjurat de ghilimele).

kaiser kaiser
31 iul. 2013 19:06:52

@s_ha_dum este setat doar pentru "true" dacă este bifat, iar dacă nu este bifat, este returnat un string gol (0 caractere).

Kegan Quimby Kegan Quimby
31 iul. 2013 19:38:08

@kaiser var_dump returnează următoarele pentru un apartament disponibil, neînchiriat: string(0) "" și pentru un apartament indisponibil, închiriat: string(1) "1"

Kegan Quimby Kegan Quimby
31 iul. 2013 19:40:04

Vezi soluția în răspuns.

kaiser kaiser
31 iul. 2013 19:57:51

@KeganQuimby ai făcut vreun progres la aceasta?

kaiser kaiser
19 aug. 2013 20:35:15
Arată celelalte 6 comentarii
Toate răspunsurile la întrebare 4
0
12

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:

  1. 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.

  2. 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.

  1. 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.)

13 nov. 2016 08:34:00
0

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 '='.

31 iul. 2013 19:28:18
0

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.

11 dec. 2013 12:58:12
0

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' => '='
)
11 dec. 2024 19:21:38