Meta değerde sırala, ancak değeri olmayan yayınları ekle


37

pre_get_postsFiltreyi kullanarak yerleşik WP aramasını değiştiriyorum, kullanıcının gönderileri (bir sürü özel gönderi türü dahil) farklı alanlara göre sıralamasını sağlıyorum.

Yine de yaşadığım sorun, WP'ye meta değerine göre sıralama yapmam gerektiğini söylediğimde, bu meta değer kümesine sahip olmayan tüm gönderileri hariç tutacağı. Bu, "Gönderiler" "Fiyat" ayarına sahip olmadığından "Öğeler" ayarından "Fiyat" deyince "Tarih" den "Tarih" e değiştirirseniz, sonuçların sayısının değişmesine neden olur.

İstediğim şey bu değil, bu yüzden TÜM gönderileri dahil etmenin bir yolu olup olmadığını - sıraladığım meta değerine sahip olmayanlar bile - ve birinin son değeri olmayanları koyduğunu bilmek istiyorum.

Birden fazla alanda nasıl sıralanacağını biliyorum ama bu yardımcı olmuyor.

Teşekkürler

Görünüşe göre bu soru ile sadece ben değilim: wp_query args içinde belirli meta_key hem de & olmadan gönderileri dahil etme yolu? ama orada çözüm yok.

Güncelleştirme

Cevabı denedim, fakat doğru anladıysam, şu anda elimde olanı bulamadım:

<?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');
}

Meta değeri bir sayıdır (adından da anlaşılacağı gibi bir fiyat depolamak için kullanılır)

Güncelleme 2

Sipariş öğelerini yorumladım ve şimdi sahip olduğum tek şey bu:

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

Bu kodla birlikte sorgu, item_priceanahtarı olmayan ve hiçbir yayının olmadığı tüm gönderileri döndürüyor gibi görünmektedir . IE sorunu şimdi tersine döndü.

Sipariş kodunu da eklersem 0 sonuç alırım.

Düzenleme: ... üç yıl sonra ... : PI yine bu sorunu yaşadı. Verilen tüm cevapları denedim, hiçbiri işe yaramadı. Bazı insanların neden çalıştıklarını düşündüklerinden emin değilim ama en azından benim için çalışmıyorlar.

Sona erdiğim çözüm save_postfiltreyi kullanmak - tüm gönderilerin sıralamak istediğim özel alana sahip olduğundan emin olmak. Biraz can sıkıcı, bunu yapmak zorundayım, ancak erken yaptığınız sürece sorun yaşamayacaksınız.

Bu durumda, yazılara bir "görünüm sayacı" oluşturuyordum ve kullanıcıların en çok okunan yayınları sıralayabilmelerini istedim. Yine, görüntüleme sayısı sıralanırken hiç görülmemiş yayınlar (sanırım pek olası değil - ama yine de) kayboldu. Tüm yayınların görüntüleme sayısının olduğundan emin olmak için bu kod parçasını ekledim:

add_action('save_post', function ($postId) {
    add_post_meta($postId, '_sleek_view_count', 0, true);
});

Lütfen bize kodunuzu gösterin. Cevap vermeyi kolaylaştırır.
kaiser

İlk: meta_queryve tax_queryher zaman bir array( array() )çok diziyi birleştirdikleri gibi. İkincisi - cevabımda belirtildiği gibi - meta_value_numsayılar için kullanmanız gerekir . Gerçekte tanımlanması gerekebilir meta_value_num(bkz. WP_Query-Codex sayfa girişi). Son, bu kadar mantıklı değil orderde ASC ve DESC yön. Bu mümkün değil. Boşluk sınırlayıcı yalnızca çalışır orderbyve birinci ASCve ikincisini sıralamasını söyleyemezsiniz DESC. Bunun posts_clausesiçin filtre var.
kaiser

Ve meta_value_numgirişlerinizin gerçek sayılar olduğundan emin olun . Çok sık görülen biri, birisinin bir rakam olduğunu söyler, fakat aslında onu veritabanında bir dize olarak kaydeder.
kaiser

Yardımlarınız için teşekkürler, bunu deneyeceğim ve size geri döneceğim. Sebebi ASC DESCo üzerinde sıralar öyle mi meta_valueiçinde ASCve datede DESCbunun işe yaradığını söyleyebilirim kadarıyla.
powerbuoy

1
@Howdy_McGee bu doğru. Özel gönderi türlerimin bazıları bu değer kümesini VAR. Bazıları yapmaz. Ve yerleşik yazı tipleri (POST ve PAGE gibi) yapmaz. Bu özel alanda sıralama yapmaya çalıştığım zaman sadece özel alanın İLE işaretli olduğunu gösteriyor.
powerbuoy

Yanıtlar:


4

Bunun iki olası çözümü var:

1. Tüm yayınların metaları var

Burada bulduğum en iyi çözüm, gönderilerin / ürünlerin geri kalanına 0 ürün fiyatını vermektir. Bunu manuel olarak yapabilirsiniz veya tüm gönderiler arasında dolaşın ve fiyat boşsa, güncelleyin.

Gelecekte bunu yönetilebilir hale getirmek için save_post, ilk eklendiklerinde onlara bağlanabilir ve bir değer verebilirsiniz (yalnızca boşsa).

2. Birden Fazla Sorgu

İlk sorguyu yaptığınız gibi çalıştırabilir ve döndürülen gönderilerin kimliklerini saklayabilirsiniz. Ardından , ilk sorgudan dönen ID'ler hariç tüm gönderiler ve sipariş tarihi için başka bir sorgu çalıştırabilirsiniz .

Daha sonra iki sonucu ayrı olarak sırayla yazdırabilir ve istediğiniz sonuçları elde edebilirsiniz.


1
Üç yıl sonra yine aynı sorunu save_postyaşadım : P Yöntemi kullanmak zorunda kaldım (sorumu kullandığım kodla güncelledim).
powerbuoy

10

Easy Peasy, 2018’de test edildi ve şu anda üretimde kullanılıyor.

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

Bu, değer belirtilmemiş, meta anahtarı olan ve olmayan tüm öğeleri kontrol eder. meta sorgusu, sipariş için anahtarı güvenilir bir şekilde sağlar. Test edilmiştir. Ancak, meta sorgusu birden çok anahtar kullandığında nasıl çalışacağından emin değilim.

Pratik örnek

/**
 * 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 );

Bu, gönderileri custom_meta_keyvarsayılan olarak sipariş edecek ve söz konusu anahtar için değeri olmayan gönderileri yoksaymayacak.


Sadece kod okumasını yapmak gibi görünüyor şeye sahip Mesajları olsun custom_meta_keywhick mesajları almak ve yok olması custom_meta_key. Sıralama ile gerçek bir çalışma örneği eklemek için çekinmeyin.
powerbuoy

1
Haklısınız, tüm yaptığı bu, ancak aşağıdaki satır meta_value'ya göre (sipariş edilen meta anahtarın) sıralanmasından sorumludur. $query->set( 'orderby', 'meta_value title' );(Meta değerine göre sırala, ardından birden fazla yayın meta anahtar için aynı değerde olduğunda başlığa göre sırala). Bu pre_get_posts, geçirilen $querydeğişken kullanılarak kancada yapılmalıdır . Sorulan sorunun meta değerine göre nasıl sıralanacağını ve bu meta anahtar için değeri olmayan gönderileri yoksaymayacağını unutmayın.
noahmason

@powerbuoy Güncelleştirilmiş güncel örneğe bakın
noahmason

Tamam, bir dahaki sefere ben bu sorunla karşı karşıyayım.
powerbuoy

1
Özel bir get_posts()aramada benim için çalıştı , _featuredmeta ile başa çıkma sözlerini iletmek , daha sonra tarihe göre sıralamak. Teşekkürler!
natebeaty

8

Bu yöntem, talep edilen ve almayanlar dahil tüm gönderileri döndürür meta_key, ancak sipariş verirken garip şeyler de yapar.

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');
}

Bunu, bu sorunun farklı cevaplarını araştırarak ve oluşturulan SQL'i deneme yanılma yoluyla analiz ederek buldum . Ayarı görünüyor array('meta_query' => array('relation' => 'OR'))uygun çıkışları LEFT JOINyerine INNER JOINgereklidir meta eksik mesajları içerecek şekilde. Belirtilmesi, cümlecikte meta alanı olmayan gönderileri filtrelemeyi NOT EXISTSönler WHERE. Bunun için WP_Query, oluşturulan SQL şöyledir (girinti / yeni satırlar eklenmiştir):

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

Sonuç, meta_value item_priceve eksik olan tüm yazıların bir listesidir item_price. İle mesajların tamamı item_pricebirbirine doğru göreceli sipariş edilebilir, ancak ileti eksik item_pricebazı rasgele kullanacak diğer meta değeri (diyelim ki, _edit_lastgibi görünüyor 1onun için benim veritabanı veya tamamen keyfidir diğer bazı iç wordpress meta verileri oldukça sık) wp_postmeta.meta_valuein ORDER BYfıkra. Bu nedenle, bu yöntem yakın ve belirli veriler için işe yaramış gibi gözükse de, bozuldu. Bu yüzden, söyleyebileceğim tek şey, eğer item_pricedeğerleriniz eksik yazılanlar için MySQL'in seçtiği rastgele meta alanlarıyla çakışmazsa item_price, bu sizin için işe yarayabilir. İhtiyacınız olan tek şey, yayınlarınızın gönderileceği bir garanti iseitem_pricediğer mesajların sıralanmasına bakılmaksızın birbirlerine göre doğru şekilde sıralanırsa, tamam olabilir. Ama bence bu sadece wordpress'te bir eksiklik. Lütfen beni düzeltin, umarım yanılıyorum ve bu sorunu çözmenin bir yolu var ;-).

Görünüşe göre INNER JOIN wp_postmeta, MySQL, verilen gönderide eksik postmetaolduğunda gönderiyle ilişkili birden çok satır arasından rastgele bir satır seçiyor meta_key. Bir SQL perspektifinden, çıktıya wordpress'in nasıl söyleneceğini bulmamız gerekir ORDER BY mt1.meta_value. NULLBizim istediğimiz meta_keyeksik olduğunda , bu sütun uygun şekilde değil wp_postmeta.meta_value. Bunu yapabilirsek, SQL bunları NULL(eksik girişleri) herhangi bir değerden önce sıralar, bize iyi tanımlanmış bir düzen verir: ilk önce belirli postmeta alanını eksik olan tüm gönderilerden sonra ikincisi alana sahip olan gönderilerden gelir. : Ama bütün sorun 'orderby' => 'meta_value'yalnızca başvurabilir 'meta_key' => 'item_price' ve unaliased wp_postmetaher zaman olduğu INNER JOINyerine hiç bir LEFT JOINanlamı wp_postmeta.meta_valueve wp_postmeta.meta_keykutuasla olmak NULL.

Bu yüzden WP_Query, bunun şimdi belgelendiği gibi wordpress'in yerleşik ifadesiyle mümkün olmadığını söylemeliyim (wordpress-3.9.1'de). Zahmet. Bu nedenle, bunun doğru şekilde çalışması için ihtiyacınız varsa, muhtemelen başka bir yere wordpress bağlamanız ve oluşturulan SQL'i doğrudan değiştirmeniz gerekir .


Çok umut verici görünüyor! Bir dahaki sefere bu sorunu deneyeceğim. Size şimdi cevabı vermek istiyorum, ama önce benim için çalıştığını onaylamayı tercih ederim.
powerbuoy

Bu her şeyin benim için ortaya çıkmasını engelledi. Bunu uyguladıktan sonra hiçbir şey gösterilmedi.
Jake

@Jake Yea burada aynı. Bugün yine bu sorunu yaşadım ve denedik. 0 sonuç verir.
powerbuoy

Siz hangi wordpress sürümünü kullanıyorsunuz? Bu yazının, wordpress tarafından desteklenmeyen ve wordpress-3.9.1 kullanıyorsanız veya bunun ötesinde çok fazla sürüm olmadığında işe yarayan dahili, belgesiz bir API'nin nasıl kullanılacağını açıkladığını düşünüyorum.
binki

2

Sanırım bir çözümüm var.

İki meta_keygönderiyi kullanabilirsiniz , biri tüm yayınlarda olanları (like "_thumbnail_id")ve meta_keyistediğiniz filtre olarak kullanmak.

Demek argümanların:

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

1
Burada sorun boş dize karşılaştırmasıdır, çıkartın ve aynı 'value' => '', zamanda ikinci karşılaştırmanın olması gerektiği NOT EXISTSve son ayar talimatı gerekmediği için çalışır
nodws 24:18

2

Buradaki herkesin sahip olduğu sorun meta sorgularının sırasına göre yapmak zorunda. Doğru bir şekilde sıralamak için, "EXISTS" sorgusunun önüne "EXISTS DEĞİL" sorgusunu koymanız gerekir .

Bunun nedeni, WordPress'in "ORDER BY" deyimindeki son "LEFT JOIN" ifadesinin meta_değerini kullanmasıdır.

Örneğin:

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

1

Uygunsa, meta değeri yoksa, bir gönderi her kaydedildiğinde veya güncellendiğinde varsayılan bir meta değeri ekleyebilirsiniz.

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

Eğer özel yazı alanı kullanıyorsanız, yerine add_action('save_post', 'addDefaultMetaValue');göre add_action('save_post_{post_type}', 'addDefaultMetaValue');örneğinadd_action('save_post_product', 'addDefaultMetaValue');


1

Sayısal meta değerleri için kendi başıma sorun yaşadım ve sorgunun sırasının da önemli olduğunu vurguladım. Benim için NOT EXISTSsorgu ilk olmalı.

Örnek:

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

Sayısal değerler için doğru yöne ulaşmak ’orderby’için ayrıca ayarlanması gereken geneldir ’meta_value_num’. Aksi takdirde, sayısal değerler için tuhaf sonuçlar elde edersiniz, örneğin:

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

Yerine:

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


1

Benzer bir sorunla da karşılaştım ve aşağıdaki çözüm bana yardımcı oldu:

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

WordPress Codex'te " çok sayıda 'meta_key'sinin bulunduğu " sipariş sırası "başlıklı bir açıklama buldum : https://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters görüntü tanımını buraya girin


0

Bunun olası bir orderbydeğeri meta_valuevar.

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

Sayısal değerleriniz varsa meta_value_numbunun yerine kullanın.

Yasal Uyarı: Bu test edilmemiştir, ancak çalışması gerekir . Önemli olan, sizin meta_keyve keydeğerlerinizi belirtmeniz gerektiğidir . Aksi halde, mevcut olmayan değerleri karşılaştıramazsınız, bu da her iki gönderi türünü sorgulamayı mümkün kılmalıdır. Bir çeşit hack-ish, ama işe yaradığı sürece ...


Cevabınız için teşekkürler, lütfen güncellenmiş sorumu kontrol edin, sizi doğru anladığımdan emin değilim.
powerbuoy

Hala bu işi yapmadım, bu yüzden eğer bir çözümünüz varsa neyi yanlış yaptığımı bilmek isterim. Ayrıca, hak talebinde bulunmak istiyorsan
SO'ya

1
İki şey. 'your_keys_name've 'your_meta_key'her ikisi de farklı olmak yerine aynı dize olmalı, aksi halde soruyu yanlış anlamışsınız gibi görünüyor. İkincisi, bunu yerel kurulumumda test ettim ve anahtarın bulunduğu tüm gönderileri ( meta_queryhiçbirinden) ve hiçbir yazının görünmemesiyle meta_keysonuçlanan anahtarın ( hiçbirinden) eksik olduğu gönderileri hariç tutar . Ancak, bu cevap, en azından sözcükleri söyleyen bir şeye doğru bir adımdır ;-).
binki

1
Sadece eklerseniz Ah, ilginçtir, bu yanıt çalışır 'relation' => 'OR'için meta_query. Tuhaf şeyler o_o.
binki

@binki Sadece soruma bir düzenleme yapın ve değiştirilmesi gerektiğini düşündüğünüz bitleri değiştirin. Bu topluluk odaklı bir site :)
kaiser

0

Sanırım @kaiser'ın yapmaya çalıştığı şey, bu meta anahtarına sahip tüm gönderileri sorguya söylemekten ibaretti, bu gönderilerin hiçbirini filtrelememek için koşullu bir kukla uygulayarak . Özel alanlarınızın alabileceği tüm değerleri biliyorsanız , x, y, z diyebilirsiniz, "NEREDE meta_key IN (x, y, z) " diyebilirsiniz , ancak fikir, bu sorunu hep birlikte söyleyerek kaçınabilmenizdir ! = (' ') :

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

Ayrıca test edilmedi ama denemeye değer gibi geliyor :-).


1
Şu anda bunu gerçekten test edemiyorum, ancak bunun yalnızca item_price'in ayarlandığı ve '' olmadığı yerlerde gönderileri döndüreceğinden eminim.
powerbuoy

0

Bunu bir parça kesmekle (IMHO) halletmek zorunda kaldım ama bu benim için işimi yaptı.

Birleştirme ve sipariş dizelerini güncellemek için posts_join_paged ve posts_orderby filtrelerine bağlanabilirsiniz . Bu, alanın belirli bir gönderi için var olduğunu varsaymak yerine, WP_Query yerine ilk katılacağınız sürece ne istediğinizi sipariş etmenizi sağlayacaktır. Daha sonra kaldırabilir meta_key, orderbysenin WP_Query args gelen ve `düzeni.

Aşağıda bir örnek. Her işlevin en üstünde, bazı durumlar için kaçmam gerekti, çünkü bunu WP_Query kullanan her şeye ekleyecekti. Özel gereksinimlerinize uyacak şekilde değiştirmeniz gerekebilir.

Bu iki filtre hakkındaki dökümantasyon ne yazık ki yoksundur, bu yüzden ... iyi şanslar! :)

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;
}

Kod çalışıyor. Ancak meta_value bir dize olarak ele alınır. Öyleyse 6, 50 olarak daha yüksek puan aldı. Onları sayı olarak ele almak mümkün herhangi bir değişiklik?
Drivingralle

@Drivingralle cast(my_custom_meta_key.meta_value as unsigned) DESChile yapmalı ...
tfrommen

1
Teşekkürler @tfmenmen. $orderby_statement = "cast(my_custom_meta_key.meta_value as unsigned) DESC";harika çalışıyor
Drivingralle

0

Bu çözüm benim için çalıştı:

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;

    }

}

Ancak, bu çözüm ilk önce null meta_value olan kayıtları gösterir. Bu diğer çözüm ASC sırasını ve sonunda boş değeri gösterir:

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 ); 
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.