Meta query dengan nilai true / false boolean

11

Saya mencoba menunjukkan semua properti sewaan, pertama oleh semua properti yang belum disewa, dan kemudian oleh semua properti yang saat ini disewa. Ada jenis pos ubahsuaian 'sewa' dengan meta pos ubahsuaian untuk harga yang disewa (_price_rented) yang merupakan kotak centang (mengembalikan baik benar atau salah ... benar jika HAS telah disewa). Saya perlu mengubah kueri untuk menampilkan semua properti dengan properti yang tersedia (tidak disewa) muncul terlebih dahulu dan kemudian properti sewaan muncul.

Ini pertanyaan saya:

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

Untuk beberapa alasan, kueri ini menunjukkan semua properti yang telah disewa. Ketika saya mengalihkan nilai dari 'false' ke 'true' di meta_query, ia tidak menampilkan properti apa pun.

Jadi, kemudian saya berpikir, nilai pengembaliannya salah (untuk properti yang disewa) atau NULL (untuk properti yang TIDAK disewa), tetapi saya tidak yakin bagaimana cara meminta hasil NULL (bukan salah), saya menambahkan ' bandingkan 'argumen dengan meta_query dan tetapkan nilainya ke'! = 'tetapi itu juga tidak berhasil.

EDIT: var_dump mengembalikan yang berikut untuk apartemen yang tersedia, tidak disewa: string(0) ""dan untuk apartemen yang tidak tersedia, disewa,:string(1) "1"

Kegan Quimby
sumber
menggunakan nilai 1 dan 0 mungkin?
reikyoushin
meta_query type => string. Nilai yang mungkin adalah 'NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'DITANDATANGANI', 'TIME', 'UNSIGNED'. Nilai default adalah 'CHAR'.
iEmanuele
@reikyoushin: menggunakan '1' mengembalikan semua properti sewaan, dan '0' tidak mengembalikan properti.
Kegan Quimby
1
@ iEmanuele: mengubah yang tampaknya tidak berpengaruh (saya pikir hal yang sama). Saya melihatnya dari artikel ini: thethemefoundry.com/blog/…
Kegan Quimby
1
Apakah _price_rentedsebenarnya ditetapkan untuk keduanya truedan falsenilai - nilai, atau hanya ditetapkan untuk true? Tolong periksa databasenya. Saya bertanya karena kotak centang tidak dicentang sama sekali tidak melewati POSTjadi saya bertanya-tanya apakah nilai ditetapkan sama sekali untuk kasus-kasus itu.
s_ha_dum

Jawaban:

4

WP_Meta_Query adalah bagian yang "tidak begitu stabil" dalam inti dan jika Anda tidak terlalu memperhatikan hal itu dapat dengan mudah pecah dari kebingungan.

Saat Anda melakukan new WP_Query()dan memiliki meta_query => array()argumen atau pasangan kunci / nilainya setara, lalu new WP_Meta_Query()melompat, langsung diikuti dengan penguraian.

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

Nilai yang diizinkan

Saat Anda menanyakan data meta, maka ada boolopsi. Dan jika Anda akan menggunakannya, maka itu akan kembali ke CHAR, yang nilai defaultnya sebagai array dari nilai yang diizinkan adalah:

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

di mana NUMERICakan diatur ulang ke SIGNED.

Debugging

Ada banyak filter yang dapat memengaruhi proses penyimpanan pasca, jadi hal pertama yang harus dilakukan adalah memeriksa nilai yang berbeda di dalam beberapa loop:

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

Kemudian, tergantung pada nilai balik, Anda harus menggunakan SIGNED, jika hasilnya 0atau 1, "true"atau "false"jika hasilnya berupa string. Jika itu benar-benar boolean, maka saya masih menyarankan untuk menggunakan stringhanya untuk memastikan itu lulus $GLOBALS['wpdb'], yang hanya dapat melewati %sstring dan %ddigit.

catatan tambahan

Seperti yang saya baru saja diperbarui entri Codex untukWP_Meta_Query hari ini, saya melihat bahwa sana sudah banyak output yang berbeda (menambahkan jumlah banyak tidak dibutuhkan JOINS, yang dibahas pada Trac sini dan di sini dengan keluar satu patch pindah ke inti) mungkin. (Tiket tindak lanjut untuk ANDbagian - bagian di sini ) Poinnya adalah memungkinkan untuk menggunakan kombinasi meta_*argumen di samping meta_queryarray dan sub-arraynya. Hasilnya hampir tidak diketahui kecuali Anda membuangnya, jadi IMHO Anda lebih baik menggunakan salah satu atau cara lain untuk menambahkan input. Terutama bila Anda hanyamenggunakan meta_key, karena ini menghasilkan "permintaan kunci saja" dalam beberapa kasus.

Larutan

Seperti yang ditunjukkan dalam komentar:

(...) var_dumpmengembalikan yang berikut untuk apartemen yang tersedia dan tidak disewa: string(0) ""dan untuk apartemen yang tidak tersedia, disewa,:string(1) "1"

Sekarang meta_queryharus digunakan

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

Jika Anda ingin mendapatkan apartemen "tidak tersedia, sewaan" atau gunakan '!='untuk mengambil apartemen "non-sewaan".

Catatan: Nilai yang mungkin untuk meta_compareare '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN', 'NOT EXISTS', 'REGEXP', 'NOT REGEXP'atau 'RLIKE'. Nilai default adalah '='.

kaisar
sumber
3

Saya menghadapi masalah yang sama dan setelah satu jam pencarian menemukan "NOT EXISTS"dan "EXISTS"nilai ( only in WP >= 3.5 ). Jadi tidak perlu meminta nilai meta cukup periksa apakah meta_key ada:

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

Ini bekerja dengan baik untuk saya.

Thibaut
sumber
3

TL; DR: Masalah ini mungkin sebagian besar terjadi ketika bidang boolean dibuat sebagai opsional. Anda dapat memperbaikinya dengan membuatnya diperlukan, atau menggunakan kueri yang lebih kompleks untuk mengambil kasing standar.

Keterangan lebih lanjut:

Ada dua masalah representasi data yang terjadi di sini: satu adalah nilai data mana yang digunakan untuk mewakili benar / salah dan yang lainnya adalah apakah lapangan disimpan atau tidak sama sekali jika itu adalah nilai default (biasanya salah).

Bagian 1: Saya melihat SQL yang dihasilkan oleh WP_Meta_Queryuntuk perbandingan benar dan salah, dan menemukan bahwa untuk benar itu menggantikan '1' dan untuk false '' (string kosong). Jadi, apa pun yang Anda tulis ke dalam basis data harus setuju dengan itu jika Anda akan melakukan kueri yang membandingkan nilai benar dan salah yang sebenarnya. Khususnya, Anda tidak ingin menulis '0' untuk false. Mungkin lebih mudah untuk menulis dan menguji 0 dan 1 sebagai gantinya (dan banyak pembangun formulir melakukan itu). Tetapi periksa untuk melihat apa yang sedang ditulis ke database dan ingatlah itu ketika membangun permintaan Anda.

Bagian 2: Dengan asumsi bahwa false adalah nilai default, menemukan catatan yang nilainya benar mudah:

... 'meta_key' => 'my_key', 'meta_value' => 1 (atau benar)

Tetapi pihak lain menantang: mungkin ada nilai yang salah, atau mungkin tidak ada nilai sama sekali. Ini bisa terjadi jika nilai terdaftar sebagai opsional dalam formulir --- maka selama pengguna tidak secara eksplisit mengatur atau mengubahnya, itu tidak akan ditambahkan ke database. Perhatikan bahwa jika Anda hanya menggunakannya get_post_metaakan berfungsi dengan baik seperti ini: mengembalikan nilai yang salah dan mengembalikan tidak ada nilai akan mencapai hal yang sama.

Tetapi ketika Anda menggunakan WP_Query, itu tidak mudah. (Atau jika ya, saya belum tahu caranya).

Anda memiliki dua (atau mungkin tiga) opsi:

  1. Pastikan bidang selalu diinisialisasi secara eksplisit ke nilai nyata. Di beberapa pembuat formulir, Anda melakukan ini dengan membuat bidang yang diperlukan dan memberinya nilai default. Maka Anda bisa menguji dengan ...'meta_value' => 0 andal.

  2. Lakukan dua kueri, yang pertama menguji nilai salah dan yang kedua menguji tanpa nilai. Ini dapat digabungkan menjadi satu WP_Query seperti ini:

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

Ini mungkin bukan permintaan yang efisien. Bergantung pada banyak faktor, mungkin lebih baik mengembalikan semua objek dan memfilternya dalam kode Anda sendiri.

  1. Dimungkinkan untuk menggunakan 'tidak ada nilai' untuk berarti false. Untuk melakukan ini, setiap kali nilai harus disetel ke false, Anda harus menghapus nilai meta alih-alih memperbaruinya .

Dalam hal itu, satu 'NOT EXISTS'permintaan akan andal mengembalikan objek yang benar. (Saya tidak berpikir banyak pembuat formulir atau plugin mendukung perilaku ini, jadi saya hanya akan menggunakannya dalam kode khusus murni.)

Denise Draper
sumber