Bagaimana saya bisa membuat meta_query dengan array sebagai meta_field?

16

Berikut adalah argumen untuk pertanyaan saya:

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        array(
            'key' => 'topics',
            'value' => 'sports',
        )
    )
);

Ini berfungsi saat topicsstring, tetapi tidak ketika array. Saya ingin agar kueri ini berfungsi ketika topicsmisalnyaarray( 'sports', 'nonprofit', etc. )

Apakah ada cara untuk membangun kueri meta dengan array sebagai meta_key?

mike23
sumber
Tolong jelaskan - maksud Anda bahwa nilai "topik" yang disimpan adalah sebuah array? Atau bahwa nilai yang disimpan adalah string, dan Anda ingin meneruskan beberapa istilah ke kueri dalam array?
MathSmath
@ MathSmath, maksud saya bahwa nilai yang disimpan adalah array.
mike23

Jawaban:

30

Mengumpankan kueri dengan nilai yang mungkin

Jika nilai dalam database adalah string dan Anda ingin memberi makan beberapa nilai query:

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        array(
            'key' => 'topics',
            'value' => array ( 'sports', 'nonprofit', 'community' ),
            'compare' => 'IN'
        )
    )
);

Mencari nilai tertentu dalam array data serial

Jika nilai dalam database adalah array dari beberapa topik dan Anda ingin mencari satu topik dalam array itu (Perhatikan bahwa array dalam database dapat diambil seperti itu, tetapi tinggal di database dalam bentuk serial, yang merupakan string juga):

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        array(
            'key' => 'topics',
            'value' => 'sports',
            'compare' => 'LIKE'
        )
    )
);

Menggunakan 'LIKE' sebagai nilai perbandingan bukanlah instruksi yang jelas seperti yang Anda harapkan, tetapi itu adalah opsi terbaik untuk digunakan.

Di samping itu, satu-satunya pilihan Anda akan mengambil semua posting yang memiliki "topik" meta_key ditetapkan dan mengulanginya secara manual atau, dengan kata lain, periksa nilai dalam loop dan menampilkan posting pada kondisi tersebut.

Johannes Pille
sumber
14

Untuk keluar dari respons Johannes, karena ini adalah array serial, jika Anda menyimpan sesuatu seperti id pengguna (yang merupakan kasus saya), Anda mungkin perlu menanganinya sedikit berbeda.

Pos meta diselamatkan seperti:

array( "1", "23", "99");

Jadi ya mereka bilangan bulat tetapi melalui update_post_metamereka diselamatkan sebagai string.

'meta_query' => array(
            array(
                    'key'     => 'my_meta_key',
                    'value'   => serialize( strval( 1 ) ),
                    'compare' => 'LIKE'
                )
            )

Jadi Anda benar-benar melakukan perbandingan SEPERTI dengan versi string serial dari apa yang Anda cari. Saya menghabiskan beberapa jam untuk mencoba mendapatkan sesuatu seperti ini untuk bekerja dan sejauh ini ini yang terbaik yang bisa saya lakukan.

sMyles
sumber
serialize (strval (1)) menyelesaikan masalah saya, Terima kasih
Behzad
Datangi jawaban lama ini secara kebetulan hari ini. Saya suka tambahan Anda. +1
Johannes Pille
Saya baru saja menemukan ini juga, hal saya adalah bahwa saya perlu mendapatkan semua posting di mana user_id tidak dalam array, tetapi solusi di atas tidak berfungsi jadi saya membuatnya seperti ini: 'meta_query' => array( array( 'key' => 'my_meta_key', 'value' => ':' . $user_id . ';', 'compare' => 'NOT LIKE' ) ) Karena ketika serial semua nilai disimpan seperti: ' :nilai;'
Bobz
4

Sedikit perbaikan dari jawaban @sMyles.

Saya memiliki kasus di mana ID telah disimpan baik sebagai string (seperti ketika diambil dari input formulir) dan sebagai bilangan bulat (misalnya update_post_meta($post_id, authorized_users', array(get_current_user_id()));). Ini seperti masalah yang terkenal di wp_set_object_terms()mana Anda dapat menggunakan ID istilah untuk menetapkan istilah, tetapi jika Anda tidak menjadikannya sebagai bilangan bulat pertama, Anda memiliki peluang 50% untuk membuat istilah baru dengan angka-angka tersebut sebagai namanya sebagai gantinya.

Ini dapat menyebabkan mereka disimpan secara sangat berbeda dalam larik serial, seperti yang dapat dilihat dari cuplikan kasus seperti itu dari basis data situs pengujian saya:

a:1:{i:0;s:1:"1";} // 's' for 'string', also note the double quotes
a:1:{i:0;i:1;} // 'i' for 'integer', no quotes

Kedua hal di atas, ketika diberi makan print_r()akan membuat sebagai

Array
(
    [0] => 1
)

Untuk memperbaikinya, saya membuat sedikit penyesuaian meta_querydengan menambahkan relationdan versi lain dari kueri yang melemparkan nilai sebagai integer, bukan string.

Inilah hasil akhirnya:

        'meta_query' => array(
            'relation' => 'OR', // Lets it know that either of the following is acceptable
            array(
                'key' => 'bcm_enm_authorized_users',
                'value'   => serialize(strval(get_current_user_id())), // Saved as string
                'compare' => 'LIKE'
            ),
            array(
                'key' => 'bcm_enm_authorized_users',
                'value'   => serialize(intval(get_current_user_id())), // Saved as integer
                'compare' => 'LIKE'
            ),
        ),

EDIT: Baru menyadari bahwa metode ini dapat menjalankan risiko tabrakan dengan indeks array, yang dapat memungkinkan seseorang akses ilegal ke materi jika mereka tidak ada dalam array, tetapi ID pengguna mereka muncul sebagai indeks. Dengan demikian, sementara ini berfungsi jika Anda memiliki masalah yang dibahas, praktik yang lebih baik adalah memastikan bahwa nilai apa pun yang ingin Anda cari dilemparkan sebagai string sebelum menyimpannya sehingga Anda dapat menggunakan metode @sMyles sebagai gantinya.

Kaji
sumber
Ini harus menjadi jawaban yang dipilih, paling dapat diandalkan
Amin
2

Saya akan mencari jawaban Johannes. Namun, saya ingin meningkatkannya karena menggunakan meta_query itu, Anda akan menemukan kasus seperti ini

nilai Anda

array('sports','movies', 'sports2');

ketika Anda mencari

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        array(
            'key' => 'topics',
            'value' => 'sports',
            'compare' => 'LIKE'
        )
    )
);

maka hasilnya akan mengembalikan 'sport' dan 'sport2'.

Untuk memperbaikinya, ubah meta_query args menjadi

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        array(
            'key' => 'topics',
            'value' => 'sports";',
            'compare' => 'LIKE'
        )
    )
);

Itu karena nilainya serialisasi dalam database, dan setiap item akan dipisahkan oleh tanda titik koma. Jadi, argumen di atas akan berhasil

Jika item dalam nilai adalah angka, Anda hanya perlu menghapus penawaran ganda "

$args = array(
        'post_type' => 'news',
        'meta_query' => array(
            array(
                'key' => 'topics',
                'value' => '1;',
                'compare' => 'LIKE'
            )
        )
    );
Ha Doan Ngoc
sumber
1

Saya mengalami sesuatu yang serupa hari ini. Saya harus menanyakan bidang hubungan ACF (Bidang Khusus Lanjutan) dengan beberapa pengguna terkait (array).

Setelah memperbarui bidang melalui php kueri tidak berfungsi. Setelah memperbaruinya melalui ACF UI, kueri berhasil.

Masalahnya adalah, bahwa kode php saya mengatur nilai hubungan menjadi nilai int, UI mengaturnya ke nilai string. Untuk memastikan keduanya berfungsi, saya menggunakan kueri ini sekarang (cocok dengan contoh di sini):

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        'relation' => 'OR',
        array(
            'key' => 'topics',
            'value' => '1;',  // works for int-array
            'compare' => 'LIKE'
        ),
        array(
            'key' => 'topics',
            'value' => '"1"',  // works for string-array
            'compare' => 'LIKE'
        ),
    )
);
Julian Stark
sumber