Kwerenda meta z logiczną wartością prawda / fałsz

11

Próbuję wyświetlić wszystkie nieruchomości do wynajęcia, najpierw wszystkie nieruchomości, które nie zostały wynajęte, a następnie wszystkie nieruchomości, które są obecnie wynajmowane. Istnieje niestandardowy typ posta „czynsz” z niestandardowym meta postem dla wynajmowanej ceny (_price_rented), który jest polem wyboru (zwraca wartość prawda lub fałsz ... prawda, jeśli został WYNAJMOWANY). Muszę zmienić zapytanie, aby wyświetlić wszystkie właściwości z dostępnymi (niewynajętymi) właściwościami pojawiającymi się najpierw, a następnie z wynajętymi właściwościami.

Oto moje zapytanie:

$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',
        ),
    ) 
) 
);

Z jakiegoś powodu to zapytanie pokazuje wszystkie właściwości, które zostały wynajęte. Gdy zmienię wartość z „false” na „true” w meta_query, nie wyświetla żadnych właściwości.

Pomyślałem więc, że zwracana wartość to false (dla nieruchomości, które są wynajmowane) lub NULL (dla nieruchomości, które NIE są wynajmowane), ale nie jestem pewien, jak zapytać o wynik NULL (nie fałsz), dodałem „ porównaj argument z meta_query i ustaw wartość na „! =”, ale to też nie zadziałało.

EDYCJA: var_dump zwraca następujące dane dla dostępnego, nie wynajętego mieszkania: string(0) ""oraz dla niedostępnego, wynajętego mieszkania:string(1) "1"

Kegan Quimby
źródło
używając wartości 1 i 0 może?
reikyoushin
meta_query type => string. Możliwe wartości to „NUMERIC”, „BINARY”, „CHAR”, „DATE”, „DATETIME”, „DECIMAL”, „SIGNED”, „TIME”, „UNSIGNED”. Wartość domyślna to „CHAR”.
iEmanuele
@reikyoushin: użycie „1” zwraca wszystkie wynajęte nieruchomości, a „0” nie zwraca żadnych nieruchomości.
Kegan Quimby
1
@ iEmanuele: zmiana nie wydaje się mieć żadnego efektu (myślałem to samo). Widziałem to z tego artykułu: thethemefoundry.com/blog/…
Kegan Quimby
1
Jest _price_rentedwłaściwie ustawiony dla obu truei falsewartości, czy jest to tylko ustawiony true? Proszę sprawdzić bazę danych. Zapytałem, ponieważ niezaznaczone pole wyboru w ogóle nie zostało przekazane, POSTwięc zastanawiam się, czy wartość jest w ogóle ustawiona dla tych przypadków.
s_ha_dum

Odpowiedzi:

4

WP_Meta_Query jest w pewnym sensie „niezbyt stabilną” częścią rdzenia i jeśli nie poświęcisz zbyt wiele uwagi, może łatwo oderwać się od pomieszania.

Kiedy wykonujesz a new WP_Query()i masz meta_query => array()argumenty lub ich ekwiwalent pojedynczej pary klucz / wartość, wtedy new WP_Meta_Query()wskakujesz, natychmiast następuje parsowanie.

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

Dozwolone wartości

Gdy przeszukujesz metadane, istnieje boolopcja. A jeśli go użyjesz, wróci do tego CHAR, do czego domyślna wartość jako tablica dozwolonych wartości to:

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

gdzie NUMERICzostanie zresetowany do SIGNED.

Debugowanie

Istnieje wiele filtrów, które mogą wpływać na proces zapisu po zapisaniu, więc pierwszą rzeczą do zrobienia jest sprawdzenie różnych wartości w pewnej pętli:

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

Następnie, w zależności od wartości zwracanej, będziesz musiał użyć SIGNED, jeśli wynikiem jest 0lub 1, "true"lub "false"jeśli wynikiem jest ciąg. Jeśli to naprawdę boolean, to nadal sugerowałbym, aby użyć, stringaby upewnić się, że przechodzi $GLOBALS['wpdb'], który może przepuszczać tylko %sciąg znaków i %dcyfrę.

Dodatkowe uwagi

Jak już aktualizowany wpis CodexuWP_Meta_Query dzisiaj, widziałem, że są tam wiele różnych wyjść (dodając liczne ilości niepotrzebnych JOINS, które są omawiane na Trac tutaj i tutaj z zewnątrz jednym plastrze przeniesiona do rdzenia) możliwych. (Kontynuacja bilet na ANDczęści tutaj ) Chodzi o to, że jest możliwe, aby użyć kombinacji meta_*argumentów obok tej meta_querytablicy i jej subarrays. Wynik jest prawie nieznany, chyba że go zrzucisz , więc IMHO lepiej jest użyć jednego lub drugiego sposobu dodawania danych wejściowych. Zwłaszcza gdy jesteś tylkoprzy użyciu meta_key, ponieważ w niektórych przypadkach powoduje to „zapytanie tylko z kluczem”.

Rozwiązanie

Jak wskazano w komentarzach:

(...) var_dumpzwraca następujące koszty dla dostępnego, nie wynajętego mieszkania: string(0) ""oraz dla niedostępnego, wynajętego mieszkania:string(1) "1"

Teraz meta_querymusi użyć

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

Jeśli chcesz uzyskać „niedostępne, wynajmowane apartamenty” lub użyć, '!='aby odzyskać „nie wynajmowane” apartamenty.

Uwaga: Możliwe wartości meta_compareto '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN', 'NOT EXISTS', 'REGEXP', 'NOT REGEXP'lub 'RLIKE'. Wartość domyślna to '='.

kajzer
źródło
3

I w obliczu tego samego problemu i po godzinie poszukiwań znaleźli "NOT EXISTS"i "EXISTS"wartości ( only in WP >= 3.5 ). Nie musisz więc pytać o wartość meta, po prostu sprawdź, czy istnieje meta_key:

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

Działa dla mnie idealnie.

Thibaut
źródło
3

TL; DR: Ten problem prawdopodobnie występuje najczęściej, gdy pole boolowskie jest tworzone jako opcjonalne. Możesz to naprawić, wymagając tego lub używając bardziej złożonego zapytania w celu odzyskania domyślnej wielkości liter.

Więcej szczegółów:

Występują tutaj dwa problemy z reprezentacją danych: jeden z nich, które wartości danych są używane do przedstawienia wartości prawda / fałsz, a drugi to, czy pole jest w ogóle przechowywane, czy jest to wartość domyślna (zazwyczaj fałsz).

Część 1: Spojrzałem na SQL wygenerowany przez WP_Meta_Querydla porównań na prawdę i fałsz, i stwierdziłem, że dla prawdy zastępuje „1” i fałsz ”(pusty ciąg znaków). Więc cokolwiek napiszesz do bazy danych, musi się z tym zgodzić, jeśli będziesz robił zapytania w porównaniu do rzeczywistych wartości prawdziwych i fałszywych. W szczególności nie chcesz pisać „0” dla fałszu. Zamiast tego może być bardziej niezawodny pisać i testować na 0 i 1 (i robi to wielu konstruktorów formularzy). Sprawdź jednak, co jest zapisywane w bazie danych i miej to na uwadze podczas tworzenia zapytania.

Część 2: Zakładając, że fałsz jest wartością domyślną, znalezienie rekordów, których wartością jest prawda, jest łatwe:

... 'meta_key' => 'my_key', 'meta_value' => 1 (lub prawda)

Ale druga strona stanowi wyzwanie: może istnieć fałszywa wartość lub może nie być żadnej wartości. Może się tak zdarzyć, jeśli wartość została wymieniona jako opcjonalna w formularzu --- wówczas, dopóki użytkownik nie ustawi jej wprost ani nie zmieni, nie zostanie dodana do bazy danych. Zauważ, że jeśli tylko get_post_metago używasz , będzie dobrze działać w ten sposób: zwracanie fałszywej wartości i zwracanie żadnej wartości nie spowoduje tego samego.

Ale kiedy używasz WP_Query, nie jest to takie proste. (A jeśli tak, to nie wiem, jak to zrobić).

Masz dwie (a może trzy) opcje:

  1. Upewnij się, że pole jest zawsze jawnie inicjowane na rzeczywistą wartość. W niektórych konstruktorach formularzy można to zrobić, wprowadzając wymagane pole i nadając mu wartość domyślną. Następnie możesz ...'meta_value' => 0 rzetelnie przetestować .

  2. Wykonaj dwa zapytania, pierwsze, które sprawdza pod kątem fałszywej wartości, a drugie, które sprawdza pod kątem braku wartości. Można je połączyć w jeden WP_Query, taki jak ten:

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

To prawdopodobnie nie jest wydajne zapytanie. W zależności od wielu czynników lepszym rozwiązaniem może być zwrócenie wszystkich obiektów i przefiltrowanie ich we własnym kodzie.

  1. Możliwe jest użycie „bez wartości”, co oznacza fałsz. Aby to zrobić, ilekroć wartość ma być ustawiona na false, musisz usunąć wartość meta zamiast ją aktualizować .

W takim przypadku pojedyncze 'NOT EXISTS'zapytanie niezawodnie zwróci prawidłowe obiekty. (Nie sądzę, aby wiele konstruktorów formularzy lub wtyczek obsługiwało to zachowanie, więc użyłbym go tylko w kodzie czysto niestandardowym).

Denise Draper
źródło