Pre_get_posts işlevini kullanarak bir yayını meta anahtarla dışlayabilir miyim?


24

Görüyorum ki birçok insan pre_get_postsyerine kanca kullanmayı tercih ediyor query_posts. Aşağıdaki kod çalışır ve "özellikli" meta anahtarına sahip tüm gönderileri gösterir.

function show_featured_posts ( $query ) {
    if ( $query->is_main_query() ) {
       $query->set( 'meta_key', 'featured' );
       $query->set( 'meta_value', 'yes' );
    }
}

add_action( 'pre_get_posts', 'show_featured_posts' );

Ama 'var mesajlar istiyoruz featured' meta_key edilecek dışlanan ana sorgudan. Bunun için kolay bir yolu var mı?

Yanıtlar:


33

Birçok kişinin query_posts yerine pre_get_posts hook kullanmayı tercih ettiğini görüyorum.

Yuppi!

Yani pre_get_postsbir filtre WP_Querynesnesi anlamına şey aracılığıyla yapabileceğini query_posts()sen aracılığıyla yapabilirsiniz $query->set()ve $query->get(). Özellikle şu özelliği kullanabiliriz meta_query(bakınız Kodeksi ):

$meta_query = array(
                 array(
                    'key'=>'featured',
                    'value'=>'yes',
                    'compare'=>'!=',
                 ),
);
$query->set('meta_query',$meta_query);

Ama .. bu orijinal 'meta sorgusu'nun yerini alır (eğer öyleyse). Bu yüzden, orijinal meta sorgusunu tamamen değiştirmek istemediğiniz sürece, şunu öneririm:

//Get original meta query
$meta_query = $query->get('meta_query');

//Add our meta query to the original meta queries
$meta_query[] = array(
                    'key'=>'featured',
                    'value'=>'yes',
                    'compare'=>'!=',
                );
$query->set('meta_query',$meta_query);

Bu şekilde meta sorgunuzu mevcut meta sorgularının yanına ekleriz.

Sen / ayarlamak istediğiniz olmayabilir relationözelliği $meta_queryiçin ANDveya OR(bütün tatmin veya en az bir meta sorguları dönüş için mesajların).

* Not: Bu tür sorgu, 'özellikli' meta anahtarına sahip, ancak değeri olmayan gönderileri döndürür yes. 'Seçili' meta anahtarın bulunmadığı gönderileri içermez. Bunu 3.5'te yapabilirsin .


Dolayısıyla, bir yazı için bir meta anahtarının boş olup olmadığını kontrol etmenin bir yolu yoktur. 3.5 dakika beklemek zorundayım. sonra. Cevabın için teşekkürler.
Carlisle

Sadece Yesve Noseçenekleriyle birlikte bir meta kutusu oluşturacağım ve varsayılan olarak 'Hayır' seçilecektir. Bir yazıyı özelliklendirmek istediğimde seçeceğim Yes. Ancak, son 5 gönderinin özellikli kalmasını istiyorum ve diğerleri ana sorguda görüntülenmeye devam ediyor. Her zaman geri dönüp seçimi değiştirmek istemiyorum, bu yüzden yalnızca en son 5 gönderiyi dışlamanın bir yolunu bulmalıyım. Stackexchange'te pek çok benzer soru gördüm ve bu öne çıkan yayınları yönetmenin kolay bir yolu olmalı. (genel performansı etkilemeyen, çok fazla sorgu oluşturmayan veya karışık sql sorguları gerektirmeyen bir yöntem)
Carlisle

BTW Tüm gönderiler için değer Yesveya ekstra bir meta anahtar oluşturmak için iyi bir fikir olup olmadığından emin değilim No. Anahtarsız olan yayınları dışlamak harika olurdu featured.
Carlisle

Bu işlev sadece PHP 7'ye yükselttikten sonra sitemde bozuldu Uncaught Error: [] operator not supported for strings, orijinali meta_queryboş döndüğü için hata atıyordu . Hiçbiri $meta_query = $query->get('meta_query');için anahtar yoksa, boş bir diziye geri düşerek etrafından dolaşabilirsiniz $meta_query = ( is_array( $query->get('meta_query') ) ) ? $query->get('meta_query') : [];.
Kevin Nugent

2

Bazılarının bunu kullanması ihtimaline karşı geçici çözümümü öne çıkan yayınlar için göndermek istiyorum. pre_get_postsBurada kanca kullanmıyorum ama query_postsikisini de kullanmıyorum . Sorun şu ki, ana sorgu ile oynamalıyım ve bir parça sql sorgusu çalıştırmalıyım. Herhangi bir uzman kodu kontrol edip, sorun olup olmadığını ve performans sorunlarına yol açmayacağını bana bildirirse mutlu olurum. Daha iyi bir yaklaşıma sahip olan ve bizimle paylaşan varsa da harika olacak.

Öne çıkan gönderiler sorgusu oluştur

<?php 

$featured_query = new WP_query( array(
    'meta_key'       =>'featured', 
    'meta_value'     =>'yes', 
    'posts_per_page' => 5, 
    'no_found_rows'  => true
    )
);

while ($featured_query->have_posts()) : 

    $featured_query->the_post(); 
    //Stuff...

endwhile; 
wp_reset_postdata(); 

?>

Ana sorguyu oluşturun, meta_key özelliğine sahip gönderileri hariç tutun, hariç tutmayı en yeni 5 gönderiyle sınırlayın ve diğerlerini gösterin.

<?php 

$excludeposts = $wpdb->get_col( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'featured' AND meta_value != '' ORDER BY post_id DESC LIMIT 0, 5" );

$main_query = new WP_Query( array(
    'post__not_in' => $excludeposts, 
    'paged' => $paged 
    ) 
);  

while ($main_query->have_posts()) : 

    $main_query->the_post();
    //Stuff...

endwhile;

?>

0

@Carlisle cevabında, özellikli olarak işaretlenmiş en son 5 mesajı hariç tutmak istiyorsanız, aşağıdakileri yapabilirsiniz. Posts_per_page sayfasını kaç tane dışlamak istediğinizi ve özellikli kategoriyi nasıl tasarladığınızı meta_query olarak değiştirin.

function cmp_exclude_featured_posts($query) {
    $exclude = array();  //Create empty array for post ids to exclude
    if ( $query->is_main_query() ) {
            $featured = get_posts(array(
                'post_type' => 'post',
                'meta_query' => array(
                    array(
                        'key' => 'featured',
                        'value' => '1',
                        'compare' => '==',
                    ),
                ),
                'posts_per_page' => 2
            ));

            foreach($featured as $hide) {
                $exclude[] = $hide->ID;
            }   

            $query->set('post__not_in', $exclude);
        }
}

add_filter( 'pre_get_posts', 'cmp_exclude_featured_posts' );
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.