Bisakah saya mengecualikan pos dengan kunci meta menggunakan fungsi pre_get_posts?

24

Saya melihat banyak orang lebih suka menggunakan pre_get_postshook daripada query_posts. Kode di bawah ini berfungsi dan menunjukkan semua posting yang memiliki kunci meta "unggulan"

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

Tapi saya ingin postingan yang memiliki ' featured' meta_key dikeluarkan dari permintaan utama. Apakah ada cara mudah untuk ini?

Carlisle
sumber

Jawaban:

33

Saya melihat banyak orang lebih suka menggunakan kait pre_get_posts daripada query_posts

Yay!

Jadi pre_get_postsmenyaring WP_Queryobjek yang berarti apa pun yang dapat Anda lakukan melalui query_posts()Anda dapat lakukan melalui $query->set()dan $query->get(). Secara khusus kita dapat menggunakan meta_queryatribut (lihat Codex ):

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

Tapi .. ini menggantikan 'permintaan meta' yang asli (jika ada). Jadi, kecuali jika Anda ingin sepenuhnya mengganti permintaan meta asli, saya sarankan:

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

Dengan cara ini kami menambahkan kueri meta kami di samping meta kueri yang ada.

Anda mungkin / mungkin tidak ingin mengatur relationproperti $meta_queryke ANDatau OR(untuk mengembalikan posting yang memenuhi semua, atau setidaknya satu, meta queri).

* Catatan: Jenis kueri ini akan mengembalikan tulisan dengan kunci meta 'unggulan', tetapi nilainya tidak yes. Itu tidak akan mencakup posting di mana kunci meta 'unggulan' tidak ada. Anda dapat melakukannya dalam 3.5 .

Stephen Harris
sumber
Jadi tidak ada cara untuk memeriksa apakah meta_key untuk posting ada atau tidak / kosong atau tidak? Saya harus menunggu 3,5. kemudian. Terima kasih untuk balasan Anda.
Carlisle
Saya hanya akan membuat kotak meta dengan Yesdan Noopsi dan 'Tidak' akan dipilih secara default. Ketika saya ingin menampilkan posting saya akan memilih Yes. Namun, saya ingin 5 posting terakhir tetap ditampilkan dan yang lain melanjutkan untuk ditampilkan pada permintaan utama. Saya tidak ingin kembali dan mengubah pilihan setiap kali jadi saya harus menemukan cara untuk mengecualikan hanya 5 posting terbaru saja. Saya melihat banyak pertanyaan serupa di stackexchange dan harus ada cara mudah untuk mengelola posting yang ditampilkan. (cara yang tidak memengaruhi kinerja umum, tidak membuat banyak kueri atau memerlukan kueri sql campuran)
Carlisle
BTW Saya tidak yakin apakah itu ide yang baik untuk membuat meta_key tambahan Yesatau Nonilai untuk semua posting. Akan lebih baik untuk mengecualikan posting yang tidak memiliki featuredkunci.
Carlisle
Fungsi ini baru saja mogok di situs saya setelah memutakhirkan ke PHP 7 melempar Uncaught Error: [] operator not supported for stringskesalahan karena yang asli meta_querykembali sebagai nol. Anda bisa mendapatkan sekitar dengan jatuh kembali ke array kosong jika tidak eksis beralih keluar $meta_query = $query->get('meta_query');untuk $meta_query = ( is_array( $query->get('meta_query') ) ) ? $query->get('meta_query') : [];.
Kevin Nugent
2

Saya ingin memposting solusi sementara saya untuk postingan unggulan jika-kalau ada orang yang memanfaatkannya. Saya tidak menggunakan pre_get_postskait di sini tetapi tidak query_postsjuga. Masalahnya adalah saya harus bermain dengan kueri utama dan harus menjalankan kueri sql. Saya akan senang jika ada pakar yang bisa memeriksa kodenya dan beri tahu saya apakah tidak apa-apa dan tidak akan menyebabkan masalah kinerja. Ini juga akan bagus jika ada yang memiliki pendekatan yang lebih baik dan membaginya dengan kami.

Buat kueri posting fitur

<?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(); 

?>

Buat kueri utama, kecualikan pos yang memiliki meta_key unggulan, batasi pengecualian ke 5 pos terbaru dan tampilkan semua lainnya.

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

?>
Carlisle
sumber
0

Sebagai respons @Carlisle, jika Anda ingin mengecualikan 5 posting terbaru yang ditandai sebagai fitur, Anda dapat melakukan hal berikut. Ubah posting_per_page menjadi berapa banyak yang ingin Anda kecualikan, dan meta_query menjadi bagaimana Anda menentukan kategori unggulan.

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' );
cpeckens
sumber