Mengurutkan pada nilai meta tetapi termasuk posting yang tidak memilikinya

37

Saya telah memodifikasi pencarian WP bawaan menggunakan pre_get_postsfilter, yang memungkinkan pengguna untuk mengurutkan posting (termasuk banyak jenis posting khusus) berdasarkan bidang yang berbeda.

Masalah yang saya alami adalah ketika saya memberi tahu WP untuk mengurutkan berdasarkan nilai meta, itu akan mengecualikan semua posting yang tidak memiliki set nilai meta itu. Ini menyebabkan jumlah hasil berubah jika Anda mengubah pengurutan dari katakan "Harga" ke "Tanggal" karena "Posting" tidak memiliki set "Harga" tetapi "Item" lakukan.

Ini bukan yang saya inginkan, jadi saya ingin tahu apakah ada cara untuk memasukkan SEMUA posting - bahkan yang tidak memiliki nilai meta yang saya sortir - dan menempatkan yang tanpa nilai terakhir.

Saya tahu cara menyortir lebih dari satu bidang tetapi itu tidak membantu.

Terima kasih

Sepertinya saya bukan satu-satunya dengan pertanyaan ini: Cara untuk memasukkan posting baik dengan & tanpa meta_key tertentu dalam args untuk wp_query? tapi tidak ada solusi di sana.

Memperbarui

Saya sudah mencoba jawabannya tetapi tidak yakin apakah saya mengerti dengan benar, inilah yang saya miliki sekarang:

<?php
function my_stuff ($qry) {
    $qry->set('meta_query', array(array(
        'key' => 'item_price', 
        'value' => '', 
        'compare' => 'NOT EXISTS'
    )));

    $qry->set('orderby', 'meta_value date'); # Sorting works with meta_value as well as meta_value_num - I've tried both
    $qry->set('order', 'ASC DESC');
    $qry->set('meta_key', 'item_price');
}

Nilai meta adalah angka (digunakan untuk menyimpan harga seperti namanya)

Perbarui 2

Saya sudah berkomentar soal pesanan dan yang saya miliki sekarang adalah ini:

<?php
$qry->set('meta_query', array(array(
    'key' => 'item_price', 
    'value' => '', 
    'compare' => 'NOT EXISTS'
)));

Dengan kode ini kueri tampaknya mengembalikan semua posting yang tidak memiliki item_pricekunci dan tidak ada posting yang memilikinya. Yaitu masalah sekarang terbalik.

Jika saya menambahkan kode-urutan juga saya mendapatkan 0 hasil.

Sunting: ... tiga tahun kemudian ... : PI mengalami masalah ini lagi. Saya mencoba semua jawaban yang diberikan dan tidak ada yang berhasil. Tidak yakin mengapa beberapa orang tampaknya berpikir mereka bekerja tetapi setidaknya mereka tidak bekerja untuk saya.

Solusi yang akhirnya saya gunakan adalah save_postfilter - memastikan semua posting memiliki bidang khusus yang ingin saya urutkan. Agak menyebalkan saya harus melakukannya, tetapi selama Anda melakukannya sejak dini, Anda mungkin tidak akan memiliki masalah.

Dalam hal ini saya sedang membangun "penghitung tampilan" pada posting dan ingin pengguna dapat mengurutkan pada posting yang paling banyak dibaca. Sekali lagi, postingan yang belum pernah dilihat (saya rasa itu tidak mungkin - tetapi masih) menghilang ketika mengurutkan pada jumlah tampilan. Saya menambahkan sedikit kode ini untuk memastikan semua posting memiliki jumlah tampilan:

add_action('save_post', function ($postId) {
    add_post_meta($postId, '_sleek_view_count', 0, true);
});
powerbuoy
sumber
Tolong tunjukkan pada kami kode Anda. Membuatnya lebih mudah dijawab.
kaiser
Pertama: meta_querydan tax_queryyang selalu merupakan array( array() )karena mereka menggabungkan beberapa array. Kedua - seperti yang disebutkan dalam jawaban saya - Anda harus menggunakan meta_value_numangka. Mungkin diperlukan untuk benar-benar mendefinisikan meta_value_num(lihat WP_Queryentri halaman -Codex). Terakhir, itu tidak masuk akal untuk ordermasuk ASC dan DESC arah. Itu tidak mungkin. Pembatas ruang hanya berfungsi untuk orderbydan Anda tidak bisa mengatakannya untuk mengurutkan yang pertama ASCdan yang kedua DESC. Itulah gunanya posts_clausesfilter.
kaiser
Dan pastikan bahwa meta_value_numentri Anda adalah bilangan real . Terlihat terlalu sering bahwa seseorang menyatakan bahwa itu adalah angka, tetapi sebenarnya menyimpannya sebagai string dalam database.
kaiser
Terima kasih atas bantuan Anda, saya akan mencoba ini dan membalas Anda. Alasannya ASC DESCadalah agar ia bisa mengurutkan di meta_valuedalam ASCdan di datedalam DESC, sejauh yang saya tahu itu berhasil.
powerbuoy
1
@Howdy_McGee itu benar. Beberapa jenis kiriman khusus saya MEMILIKI nilai ini ditetapkan. Beberapa tidak. Dan tipe posting bawaan (seperti POST dan PAGE) tidak. Jadi setiap kali saya mencoba untuk mengurutkan pada bidang khusus itu hanya posting DENGAN bidang kustom muncul.
powerbuoy

Jawaban:

4

Ada dua solusi yang memungkinkan untuk ini:

1. Semua posting memiliki meta

Solusi terbaik yang saya temukan di sini adalah memberikan sisa barang / produk harga barang 0. Anda dapat melakukan ini secara manual, atau loop melalui semua posting dan jika harga kosong maka perbarui.

Untuk membuat ini dapat dikelola di masa mendatang, Anda dapat menghubungkan save_postdan memberi mereka nilai saat pertama kali ditambahkan (hanya jika kosong).

2. Banyak Pertanyaan

Anda dapat menjalankan kueri pertama saat melakukan dan menyimpan ID kiriman yang dikembalikan. Anda kemudian dapat menjalankan kueri lain untuk semua posting dan tanggal orderby, tidak termasuk ID yang kembali dari kueri pertama.

Anda kemudian dapat mencetak dua hasil secara terpisah dan Anda akan mendapatkan hasil yang diinginkan.

Steven Jones
sumber
1
Tiga tahun kemudian dan saya memiliki masalah yang sama lagi: P Harus menggunakan save_postmetode ini (Saya telah memperbarui pertanyaan saya dengan kode yang saya gunakan).
powerbuoy
10

Easy Peasy, baru diuji 2018, menggunakan dalam produksi saat ini.

$query->set( 'meta_query', array(
    'relation' => 'OR',
    array(
        'key' => 'custom_meta_key', 
        'compare' => 'EXISTS'
    ),
    array(
        'key' => 'custom_meta_key', 
        'compare' => 'NOT EXISTS'
    )
) );
$query->set( 'orderby', 'meta_value title' ); 

Ini memeriksa semua item dengan dan tanpa kunci meta, tanpa nilai yang ditentukan. meta query menyediakan kunci untuk orderby dengan andal. Sudah diuji. Namun saya tidak yakin bagaimana cara kerjanya ketika kueri meta menggunakan beberapa kunci.

Contoh praktis

/**
 * Modifies query before retrieving posts. Sets the 
 * `meta_query` and `orderby` param when no `orderby` 
 * param is set, (default ordering).
 * 
 * @param   WP_Query  $query  The full `WP_Query` object.
 * @return  void
 */
function example_post_ordering( $query ) {

    // if not in wp-admin, 
    // and the query is the main query, 
    // and the query is not a singular query, 
    // and the query does not have an orderby param set...
    // Note: check for post types, etc. here as desired.
    if ( ! is_admin() 
    && $query->is_main_query() 
    && ! $query->is_singular() 
    && empty( $query->get( 'orderby' ) ) ) {

        // Setting just `meta_key` is not sufficient, as this 
        // will ignore posts that do not yet, or never will have 
        // a value for the specified key. This meta query will 
        // register the `meta_key` for ordering, but will not 
        // ignore those posts without a value for this key.
        $query->set( 'meta_query', array(
            'relation' => 'OR',
            array(
                'key' => 'custom_meta_key', 
                'compare' => 'EXISTS'
            ),
            array(
                'key' => 'custom_meta_key', 
                'compare' => 'NOT EXISTS'
            )
        ) );

        // Order by the meta value, then by the title if multiple 
        // posts share the same value for the provided meta key.
        // Use `meta_value_num` if the meta values are numeric.
        $query->set( 'orderby', 'meta_value title' );
    }

}

add_action( 'pre_get_posts', 'example_post_ordering', 10 );

Ini akan memesan posting secara custom_meta_keydefault, dan tidak akan mengabaikan posting tanpa nilai untuk kunci itu.

noahmason
sumber
Hanya dari membaca kode, yang tampaknya dilakukan hanyalah mendapatkan posting yang memiliki custom_meta_keydan mendapatkan postingan yang tidak dimiliki custom_meta_key. Jangan ragu untuk memasukkan contoh kerja aktual dengan penyortiran.
powerbuoy
1
Anda benar, hanya itu yang dilakukannya, tetapi baris di bawah ini bertanggung jawab untuk memesan dengan meta_value (dari kunci meta yang ditanyai). $query->set( 'orderby', 'meta_value title' );(Pesan berdasarkan nilai meta, lalu dengan judul saat beberapa pos memiliki nilai yang sama untuk kunci meta). Ini harus dilakukan di pre_get_postshook, menggunakan $queryvariabel yang dikirimkan . Perlu diingat pertanyaan yang diajukan adalah bagaimana cara memesan berdasarkan nilai meta, sementara tidak mengabaikan posting yang tidak memiliki nilai untuk kunci meta itu.
noahmason
@powerbuoy Lihat contoh praktis yang diperbarui
noahmason
Baiklah saya akan mencobanya lain kali saya menghadapi masalah ini.
powerbuoy
1
Bekerja untuk saya dalam get_posts()panggilan khusus untuk mendorong posting dengan _featuredmeta ke atas, lalu pesan berdasarkan tanggal setelah itu. Terima kasih!
natebeaty
8

Metode ini akan mengembalikan semua posting termasuk yang dengan dan tanpa yang diminta meta_key , tetapi akan melakukan hal-hal aneh ketika memesan.

add_action('pre_get_posts', 'my_stuff');
function my_stuff ($qry) {
    $qry->set(
        'meta_query',
        array(
            'relation' => 'OR', # Matches to this meta_query should be added to those matching the 'meta_key' query
            array(
                'key' => 'item_price', 
                'value' => 'bug #23268', 
                'compare' => 'NOT EXISTS'
            )
        )
    );

    $qry->set('orderby', 'meta_value date'); # Sorting works with meta_value as well as meta_value_num - I've tried both
    $qry->set('order', 'ASC DESC');
    $qry->set('meta_key', 'item_price');
}

Saya menemukan ini dengan mengutak-atik semua jawaban yang berbeda untuk pertanyaan ini dan menganalisis SQL yang dihasilkan melalui trial and error. Tampaknya pengaturan array('meta_query' => array('relation' => 'OR'))output yang sesuai LEFT JOINbukan INNER JOINyang diperlukan untuk memasukkan posting yang kehilangan metadata. Menentukan klausa NOT EXISTSmencegah WHEREpenyaringan posting yang tidak memiliki bidang meta. Untuk ini WP_Query, SQL yang dihasilkan adalah (indentasi / baris baru ditambahkan):

SELECT SQL_CALC_FOUND_ROWS
    wp_posts.ID
    FROM wp_posts
    INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
    INNER JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id
    LEFT JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id AND mt1.meta_key = 'item_price')
    WHERE 1=1
    AND ( wp_term_relationships.term_taxonomy_id IN (2) )
    AND wp_posts.post_type = 'post'
    AND (wp_posts.post_status = 'publish'
        OR wp_posts.post_status = 'private')
    AND (wp_postmeta.meta_key = 'item_price'
        -- Oh look, here we give SQL permission to choose a random
        -- row from wp_postmeta when this particular post is missing
        -- 'item_price':
        OR  mt1.post_id IS NULL )
    GROUP BY wp_posts.ID
    ORDER BY wp_postmeta.meta_value,wp_posts.post_date DESC
    LIMIT 0, 10

Hasilnya adalah daftar semua posting dengan meta_value item_pricedan mereka yang hilang item_price. Semua pos dengan item_priceakan dipesan dengan benar relatif satu sama lain, tetapi pos yang hilang item_priceakan menggunakan beberapa nilai meta acak lainnya (misalnya, _edit_lastyang tampaknya1 cukup sering di database saya atau beberapa metadata wordpress internal lain yang sepenuhnya arbitrer) untuk itu wp_postmeta.meta_valuedalam yang ORDER BYklausa. Jadi, sementara metode ini dekat dan mungkin berfungsi untuk data tertentu, itu rusak. Jadi, yang bisa saya katakan adalah, jika item_pricenilai Anda kebetulan tidak bertentangan dengan bidang meta acak yang dipilih MySQL untuk pos yang hilang item_price, ini mungkin bekerja dengan baik untuk Anda. Jika semua yang Anda butuhkan adalah jaminan bahwa posting Anda denganitem_pricedipesan dengan benar relatif satu sama lain tanpa memperhatikan urutan posting lain, mungkin OK. Tapi saya pikir ini hanya kekurangan di wordpress. Tolong koreksi saya, saya harap saya salah dan ada cara untuk mengatasi ini ;-).

Tampaknya untuk INNER JOIN wp_postmeta, MySQL memilih baris acak dari antara beberapa postmetabaris yang terkait dengan pos ketika meta_keyada yang hilang dari pos yang diberikan. Dari perspektif SQL, kita perlu mencari tahu bagaimana cara memberitahu wordpress ke output ORDER BY mt1.meta_value. Kolom ini benar NULLketika permintaan kami meta_keytidak ada, tidak seperti wp_postmeta.meta_value. Jika kita bisa melakukan itu, SQL akan mengurutkan ini NULL(entri yang hilang) sebelum nilai lain, memberikan kita urutan yang jelas: pertama datang semua posting yang hilang bidang postmeta tertentu, kedua datang tulisan yang memiliki bidang. Tapi itu adalah keseluruhan masalahnya: 'orderby' => 'meta_value'hanya bisa merujuk 'meta_key' => 'item_price' dan yang tidak berubah wp_postmetaselalu merupakan, INNER JOINbukan LEFT JOINmakna, wp_postmeta.meta_valuedan wp_postmeta.meta_keybisatidak akan pernahNULL .

Jadi saya kira saya harus mengatakan bahwa ini tidak mungkin dengan built-in wordpress WP_Queryseperti yang sekarang didokumentasikan (di wordpress-3.9.1). Mengganggu. Jadi jika Anda benar-benar membutuhkan ini untuk bekerja dengan benar, Anda mungkin perlu menghubungkan ke wordpress di tempat lain dan memodifikasi SQL yang dihasilkan secara langsung .

binki
sumber
Terlihat sangat menjanjikan! Saya akan coba ini lain kali kalau ada masalah. Saya ingin memberikan jawaban kepada Anda saat ini, tetapi saya lebih suka memastikannya berfungsi untuk saya terlebih dahulu.
powerbuoy
Ini membuat segalanya tidak muncul untuk saya. Tidak ada yang terlihat setelah menerapkan ini.
Jake
@Jake Yea sama di sini. Punya masalah ini lagi hari ini dan coba ini. Mengembalikan 0 hasil.
powerbuoy
Apa versi wordpress yang Anda gunakan? Saya pikir posting ini menjelaskan cara menggunakan internal, API tidak berdokumen yang tidak didukung oleh wordpress dan jadi mungkin hanya berfungsi jika Anda menggunakan wordpress-3.9.1 atau tidak terlalu banyak versi di luar itu.
binki
2

Saya rasa saya punya solusi.

Anda dapat menggunakan dua meta_keys, satu yang dimiliki semua pos (like "_thumbnail_id"), dan yang meta_keyingin Anda gunakan sebagai filter.

Jadi argumen Anda:

$qry->set(
    'meta_query',
    array(
        'relation' => 'OR',
        array(
            'key' => 'item_price', 
            'value' => '', 
            'compare' => 'EXISTS'
        ),
        array(
            'key' => 'item_price', 
            'value' => '', 
            'compare' => 'EXISTS'
        )
    )
);

$qry->set('orderby', 'meta_value date'); # Sorting works with meta_value as well as meta_value_num - I've tried both
$qry->set('order', 'ASC DESC');
$qry->set('meta_key', 'item_price');
Rafael M31
sumber
1
Masalahnya di sini adalah perbandingan string kosong, hapus dan berfungsi 'value' => '', juga perbandingan kedua harus NOT EXISTSdan instruksi set terakhir tidak diperlukan
nodws
2

Masalah yang harus dihadapi semua orang di sini adalah dengan urutan meta queries. Untuk mengurutkan dengan benar, Anda harus memasukkan kueri "BUKAN ADA" sebelum kueri "ADA".

Alasannya adalah karena WordPress menggunakan meta_value dari pernyataan "LEFT JOIN" terakhir di klausa "ORDER BY".

Sebagai contoh:

$pageQuery = new WP_Query([
    'meta_query' => [
        'relation' => 'OR',
        ['key' => 'item_price', 'compare' => 'NOT EXISTS'], // this comes first!
        ['key' => 'item_price', 'compare' => 'EXISTS'],
    ],
    'order' => 'DESC',
    'orderby' => 'meta_value_num',
    'post_status' => 'publish',
    'post_type' => 'page',
    'posts_per_page' => 10,
]);
Paul
sumber
1

Jika cocok, Anda dapat menambahkan nilai meta default setiap kali posting disimpan atau diperbarui, jika nilai meta tidak ada.

function addDefaultMetaValue($post_id) {
    add_post_meta($post_id, 'item_price', 0, true);
}
add_action('save_post', 'addDefaultMetaValue');

Jika Anda menggunakan jenis posting khusus, ganti add_action('save_post', 'addDefaultMetaValue');dengan add_action('save_post_{post_type}', 'addDefaultMetaValue');misalnyaadd_action('save_post_product', 'addDefaultMetaValue');

rjpedrosa
sumber
1

Saya memiliki masalah sendiri untuk nilai meta numerik dan menunjukkan bahwa urutan kueri juga penting. Bagi saya NOT EXISTSkueri harus menjadi yang pertama.

Contoh:

$query->set( 'orderby', 'meta_value_num' );
$query->set( 'meta_query', [
    'relation' => 'OR',
    [ 'key' => 'your_meta_name', 'compare' => 'NOT EXISTS' ],
    [
        'key' => 'your_meta_name',
        'compare' => 'EXISTS',
    ],
] );

Juga penting untuk mendapatkan arah yang benar untuk nilai numerik adalah umum yang ’orderby’harus diatur ’meta_value_num’. Kalau tidak, Anda memiliki hasil aneh untuk nilai numerik, misalnya:

1, 2, 20, 21, 3, 4, 5…

Dari pada:

1, 2, 3, 4, 5… 20, 21

KittMedia
sumber
1

Saya juga mengalami masalah serupa dan solusi berikut membantu saya:

$args = array(
'post_type' => 'kosh_products',
'posts_per_page' => -1,
'meta_query' => array(
    'relation' => 'OR',
    'category_sort_order' => array(
        'key' => '_sort_order',
        'compare' => 'EXISTS'
    ),
    'category_sort_order_not_exists' => array(
        'key' => '_sort_order',
        'compare' => 'NOT EXISTS'
    ), 
),
'orderby' => array( 
    'category_sort_order' => 'ASC',
    'date' => 'ASC'
));
$query = new WP_Query( $args );

Saya menemukan deskripsi di WordPress Codex dengan judul " 'orderby' dengan beberapa 'meta_key's ": https://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters masukkan deskripsi gambar di sini

Ilya Kogan
sumber
0

Ada kemungkinan orderbynilai meta_valueuntuk itu.

$query = new WP_Query( array ( 
    'meta_key'   => 'your_keys_name',
    'orderby'    => 'meta_value',
    'order'      => 'DESC',
    'meta_query' => array( array(
         'key'     => 'your_meta_key',
         'value'   => '',
         'compare' => 'NOT EXISTS',
         // 'type'    => 'CHAR',
    ) )
) );

Jika Anda mendapat nilai numerik, gunakan meta_value_numsaja.

Penafian: Ini tidak diuji, tetapi harus bekerja. Intinya adalah bahwa Anda perlu menentukan nilai meta_keydan keynilai Anda. Jika tidak, Anda tidak dapat membandingkan dengan nilai yang tidak ada, yang seharusnya memungkinkan untuk menanyakan kedua jenis posting. Ini semacam hack-ish, tapi selama itu berhasil ...

kaisar
sumber
Terima kasih atas jawaban Anda, silakan periksa pertanyaan saya yang diperbarui, saya tidak yakin saya mengerti Anda dengan benar.
powerbuoy
Saya masih belum membuat ini bekerja jadi jika Anda memiliki solusi saya ingin tahu apa yang saya lakukan salah. Juga, saya menetapkan karunia pada SO jika Anda ingin mengklaimnya: stackoverflow.com/questions/17016770/…
powerbuoy
1
Dua hal. 'your_keys_name'dan 'your_meta_key'keduanya harus string yang sama, bukannya berbeda, jika tidak, sepertinya Anda telah salah paham pertanyaannya. Kedua, saya menguji ini pada pengaturan lokal saya dan mengecualikan posting mana pun kunci ada (melalui meta_query) dan mengecualikan setiap posting di mana kunci hilang (melalui meta_key) sehingga tidak ada posting yang ditampilkan. Namun, jawaban ini adalah langkah menuju sesuatu yang kata-kata setidaknya ;-).
binki
1
Oh, menarik, jawaban ini tidak bekerja jika Anda hanya menambahkan 'relation' => 'OR'untuk meta_query. Hal aneh o_o.
binki
@binki Kirimkan saja edit ke pertanyaan saya dan ubah bit yang menurut Anda harus diubah. Ini adalah situs yang didorong oleh komunitas :)
kaiser
0

Saya pikir apa yang @kaiser coba lakukan adalah memberi tahu kueri untuk mengembalikan semua posting yang memiliki kunci meta dengan menerapkan semacam dummy di mana syaratnya untuk tidak menyaring posting-posting itu. Jadi, jika Anda tahu semua nilai yang dapat diambil bidang kustom Anda adalah x, y, z Anda bisa mengatakan "WHERE meta_key IN (x, y, z) " tetapi idenya adalah Anda dapat menghindari masalah itu bersama-sama dengan mengatakan ! = (' ') :

$query = new WP_Query( array ( 
    'orderby'    => 'meta_value_num',
    'order'      => 'DESC',
    'meta_query' => array( array(
         'key'     => 'item_price',
         'value'   => '',
         'compare' => '!=',
    ) )
) );

Juga tidak diuji tetapi rasanya layak untuk dicoba :-).

Jon
sumber
1
Tidak dapat benar-benar menguji ini sekarang, tetapi cukup yakin bahwa hanya akan mengembalikan posting di mana item_price diatur dan bukan ''.
powerbuoy
0

Saya akhirnya menyelesaikan ini dengan sedikit hack (IMHO), tapi itu berhasil bagi saya dalam kasus saya.

Anda dapat menghubungkan ke filter posts_join_paged dan posts_orderby untuk memperbarui gabung dan memesan string. Ini akan memungkinkan Anda untuk memesan dengan apa pun yang Anda inginkan selama Anda bergabung terlebih dahulu daripada WP_Query dengan asumsi bahwa bidang tersebut harus ada untuk pos tertentu. Anda kemudian dapat menghapus meta_key,orderby dan `perintah dari args WP_Query Anda.

Di bawah ini adalah contohnya. Di bagian atas setiap fungsi saya harus melarikan diri untuk kasus-kasus tertentu karena akan menambahkan ini ke semua yang menggunakan WP_Query. Anda mungkin perlu memodifikasinya agar sesuai dengan kebutuhan khusus Anda.

Dokumentasi pada kedua filter ini sayangnya kurang begitu ... semoga berhasil! :)

add_filter('posts_join_paged', 'edit_join', 999, 2);
add_filter('posts_orderby', 'edit_orderby', 999, 2);

/**
 * Edit join
 *
 * @param string $join_paged_statement
 * @param WP_Query $wp_query
 * @return string
 */
function edit_join($join_paged_statement, $wp_query)
{
    global $wpdb;
    if (
        !isset($wp_query->query)
        || $wp_query->is_page
        || $wp_query->is_admin
        || (isset($wp_query->query['post_type']) && $wp_query->query['post_type'] != 'my_custom_post_type')
    ) {
        return $join_paged_statement;
    }

    $join_to_add = "
        LEFT JOIN {$wpdb->prefix}postmeta AS my_custom_meta_key
            ON ({$wpdb->prefix}posts.ID = my_custom_meta_key.post_id
                AND my_custom_meta_key.meta_key = 'my_custom_meta_key')
    ";

    // Only add if it's not already in there
    if (strpos($join_paged_statement, $join_to_add) === false) {
        $join_paged_statement = $join_paged_statement . $join_to_add;
    }

    return $join_paged_statement;
}

/** 
 * Edit orderby
 *
 * @param string $orderby_statement
 * @param WP_Query $wp_query
 * @return string
 */
function edit_orderby($orderby_statement, $wp_query)
{
    if (
        !isset($wp_query->query)
        || $wp_query->is_page
        || $wp_query->is_admin
        || (isset($wp_query->query['post_type']) && $wp_query->query['post_type'] != 'my_custom_post_type')
    ) {
        return $orderby_statement;
    }

    $orderby_statement = "my_custom_meta_key.meta_value DESC";

    return $orderby_statement;
}
Cakar Berantakan
sumber
Kode berfungsi. Tetapi meta_value ditangani sebagai string. Jadi 6 dinilai lebih tinggi sebagai 50. Adakah modifikasi yang mungkin untuk memperlakukannya sebagai angka?
Mengemudi
@Drivingralle cast(my_custom_meta_key.meta_value as unsigned) DESCharus melakukan trik ...
tfrommen
1
Terima kasih @tfrommen. $orderby_statement = "cast(my_custom_meta_key.meta_value as unsigned) DESC";bekerja dengan baik.
Drivingralle
0

Solusi ini bekerja untuk saya:

add_action( 'pre_get_posts', 'orden_portfolio' );
function orden_portfolio( $query ) {

    if( ! is_admin() ) {

        $query->set( 'orderby', 'meta_value_num' );
        $query->set( 'order', 'ASC' );
        $query->set( 'meta_query', [
            'relation' => 'OR',
            [ 
                'key' => 'ce_orden', 
                'compare' => 'NOT EXISTS' ],
            [
                'key' => 'ce_orden',
                'compare' => 'EXISTS',
            ],
        ] );

        return $query;

    }

}

Namun, solusi ini pertama-tama menunjukkan catatan dengan meta_value nol. Solusi lain ini menunjukkan urutan dan null ASC pada akhirnya:

function custom_join($join) {
    global $wpdb;

    if( ! is_admin() ) {
        $join .= $wpdb->prepare(
        ' LEFT JOIN ' . $wpdb->postmeta . ' cpm ON cpm.post_id = ' . $wpdb->posts . '.ID AND cpm.meta_key = %s'
        , 'ce_orden' );
    }

    return $join;
}

add_filter('posts_join','custom_join');

function custom_orderby($orderby_statement){
    global $wpdb;

    if ( ! is_admin() ) {
        $orderby_statement = "CAST( COALESCE(cpm.meta_value,99999) as SIGNED INTEGER) ASC";
    }

    return $orderby_statement;
}

add_filter('posts_orderby','custom_orderby', 10, 2 ); 
jpussacq
sumber