ฉันสามารถยกเว้นการโพสต์ด้วยเมตาคีย์โดยใช้ฟังก์ชัน pre_get_posts ได้หรือไม่


24

ผมเห็นหลายคนชอบที่จะใช้เบ็ดแทนpre_get_posts query_postsรหัสด้านล่างใช้งานได้และแสดงการโพสต์ทั้งหมดที่มีเมตาคีย์ "เด่น"

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

แต่ฉันต้องการให้โพสต์ที่มีfeaturedmeta_key '' ถูกแยกออกจากข้อความค้นหาหลัก มีวิธีที่ง่ายสำหรับสิ่งนี้หรือไม่?

คำตอบ:


33

ฉันเห็นคนจำนวนมากชอบใช้ pre_get_posts hook แทนที่จะเป็น query_posts

เย้!

ดังนั้นpre_get_postsกรองWP_Queryวัตถุซึ่งหมายถึงสิ่งที่คุณสามารถทำผ่านquery_posts()ที่คุณสามารถทำได้ผ่านทางและ$query->set() $query->get()โดยเฉพาะอย่างยิ่งเราสามารถใช้ประโยชน์จากmeta_queryคุณลักษณะ (ดูCodex ):

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

แต่ .. สิ่งนี้จะแทนที่ 'แบบสอบถามเมตา' ดั้งเดิม (ถ้ามี) ดังนั้นหากคุณไม่ต้องการแทนที่แบบสอบถามเมตาเดิมทั้งหมดฉันขอแนะนำ:

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

วิธีนี้เราเพิ่มการสืบค้นเมตาของเราควบคู่ไปกับการสืบค้นเมตาที่มีอยู่

คุณอาจ / อาจไม่ต้องการตั้งค่าrelationคุณสมบัติของ$meta_queryเป็นANDหรือOR(เพื่อส่งคืนโพสต์ที่ตรงกับข้อความค้นหาทั้งหมดหรืออย่างน้อยหนึ่งรายการ)

* หมายเหตุ:ชนิดของแบบสอบถามนี้จะกลับโพสต์กับ 'จุดเด่น' คีย์ meta yesแต่มีค่าไม่ได้ จะไม่รวมโพสต์ที่ไม่มีคีย์เมตา 'ที่โดดเด่น' คุณจะสามารถที่จะทำเช่นนี้ใน 3.5


ดังนั้นจึงไม่มีวิธีการตรวจสอบว่ามี meta_key สำหรับโพสต์อยู่หรือไม่ / ว่างเปล่าหรือไม่? ฉันจะต้องรอ 3.5 แล้วก็ ขอบคุณสำหรับการตอบกลับของคุณ.
Carlisle

ฉันก็จะสร้างกล่องเมตาด้วยYesและNoตัวเลือกและ 'ไม่' จะถูกเลือกโดยค่าเริ่มต้น Yesเมื่อฉันต้องการที่จะมีการโพสต์ผมจะเลือก อย่างไรก็ตามฉันต้องการให้โพสต์ 5 โพสต์สุดท้ายยังคงโดดเด่นและโพสต์อื่น ๆ จะปรากฏในข้อความค้นหาหลัก ฉันไม่ต้องการย้อนกลับและเปลี่ยนการเลือกทุกครั้งดังนั้นฉันจึงต้องหาวิธียกเว้นเฉพาะ 5 โพสต์ล่าสุดเท่านั้น ฉันเห็นคำถามที่คล้ายกันมากมายใน stackexchange และควรมีวิธีที่ง่ายในการจัดการโพสต์ที่โดดเด่นเหล่านั้น (ทางที่ไม่ส่งผลกระทบต่อประสิทธิภาพการทำงานทั่วไปที่ไม่ได้สร้างจำนวนมากของคำสั่งหรือต้องมีคำสั่ง SQL ผสม)
คาร์ไลส์

BTW ฉันไม่แน่ใจว่าเป็นความคิดที่ดีหรือไม่ที่จะสร้าง meta_key เพิ่มเติมพร้อมYesหรือNoค่าสำหรับโพสต์ทั้งหมด มันเป็นการดีที่จะยกเว้นการโพสต์เหล่านั้นซึ่งก็ไม่มีfeaturedกุญแจ
Carlisle

ฟังก์ชั่นนี้พังลงในเว็บไซต์ของฉันหลังจากอัปเกรดเป็น PHP 7 แล้วเกิดUncaught Error: [] operator not supported for stringsข้อผิดพลาดเนื่องจากต้นฉบับmeta_queryกลับมาเป็นโมฆะ คุณจะได้รับรอบได้โดยการกลับไปยังอาร์เรย์ว่างลดลงถ้าไม่มีการเปลี่ยนที่มีอยู่ออกมาสำหรับ$meta_query = $query->get('meta_query'); $meta_query = ( is_array( $query->get('meta_query') ) ) ? $query->get('meta_query') : [];
Kevin Nugent

2

ฉันต้องการโพสต์โซลูชันชั่วคราวของฉันสำหรับโพสต์เด่นในกรณีที่บางคนอาจใช้ประโยชน์จากมัน ฉันไม่ได้ใช้pre_get_postsเบ็ดที่นี่ แต่ไม่ใช่query_postsอย่างใดอย่างหนึ่ง ปัญหาคือฉันต้องเล่นกับแบบสอบถามหลักและต้องเรียกใช้แบบสอบถาม sql ฉันยินดีหากผู้เชี่ยวชาญตรวจสอบรหัสและแจ้งให้เราทราบว่าใช้ได้หรือไม่และจะไม่ทำให้เกิดปัญหาประสิทธิภาพการทำงาน มันจะดีถ้าใครมีวิธีที่ดีกว่าและแบ่งปันกับเรา

สร้างแบบสอบถามโพสต์ที่โดดเด่น

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

?>

สร้างการสืบค้นหลักยกเว้นการโพสต์ที่มี meta_key เด่น จำกัด การยกเว้นไว้ที่ 5 การโพสต์ล่าสุดและแสดงรายการอื่น ๆ ทั้งหมด

<?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 หากคุณต้องการยกเว้นโพสต์ล่าสุดที่มีการทำเครื่องหมาย 5 ข้อคุณสามารถทำสิ่งต่อไปนี้ เปลี่ยน posts_per_page เป็นจำนวนที่คุณต้องการยกเว้นและ meta_query เป็นวิธีที่คุณกำหนดหมวดหมู่วิดีโอเด่น

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' );
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.