Tôi có thể loại trừ một bài đăng bằng khóa meta bằng hàm pre_get_posts không?


24

Tôi thấy nhiều người thích sử dụng pre_get_postshook thay vì query_posts. Mã bên dưới hoạt động và hiển thị tất cả các bài đăng có khóa meta "đặc trưng"

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

Nhưng tôi muốn các bài đăng có ' featured' meta_key bị loại khỏi truy vấn chính. Có một cách dễ dàng cho việc này?

Câu trả lời:


33

Tôi thấy nhiều người thích sử dụng hook pre_get_posts thay vì query_posts

Yay!

Vì vậy, pre_get_postslọc một WP_Queryđối tượng có nghĩa là bất cứ điều gì bạn có thể làm thông qua query_posts()bạn có thể làm thông qua $query->set()$query->get(). Cụ thể, chúng ta có thể sử dụng meta_querythuộc tính (xem Codex ):

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

Nhưng .. điều này thay thế cho 'truy vấn meta' ban đầu (nếu có). Vì vậy, trừ khi bạn muốn thay thế hoàn toàn truy vấn meta ban đầu, tôi đề nghị:

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

Bằng cách này, chúng tôi thêm truy vấn meta cùng với các truy vấn meta hiện có.

Bạn có thể / không muốn thiết lập các relationtài sản của $meta_queryđể ANDhoặc OR(để trở lại bài viết mà đáp ứng tất cả, hoặc ít nhất là một, truy vấn meta).

* Lưu ý: Loại truy vấn này sẽ trả về các bài đăng có khóa meta 'đặc trưng', nhưng giá trị của nó thì không yes. Nó sẽ không bao gồm các bài đăng mà khóa meta 'đặc trưng' không tồn tại. Bạn sẽ có thể làm điều này trong 3.5 .


Vì vậy, không có cách nào để kiểm tra xem meta_key cho bài đăng có tồn tại hay không / có trống hay không? Tôi sẽ phải chờ 3.5. sau đó. Cảm ơn vì đã trả lời.
Carlisle

Tôi chỉ đơn giản sẽ tạo một hộp meta với YesNocác tùy chọn và 'Không' sẽ được chọn theo mặc định. Khi tôi muốn đăng một bài tôi sẽ chọn Yes. Tuy nhiên, tôi muốn 5 bài đăng cuối cùng được giữ nguyên và những bài khác được hiển thị trên truy vấn chính. Tôi không muốn quay lại và thay đổi lựa chọn mọi lúc nên tôi phải tìm cách loại trừ chỉ 5 bài đăng gần đây nhất. Tôi thấy nhiều câu hỏi tương tự trên stackexchange và nên có một cách dễ dàng để quản lý các bài đăng nổi bật đó. (một cách không ảnh hưởng đến hiệu suất chung, không tạo ra nhiều truy vấn hoặc yêu cầu truy vấn sql hỗn hợp)
Carlisle

BTW Tôi không chắc chắn liệu có nên tạo thêm meta_key với Yeshoặc Nogiá trị cho tất cả các bài đăng hay không. Sẽ thật tuyệt nếu loại trừ những bài viết đơn giản là thiếu featuredchìa khóa.
Carlisle

Hàm này vừa bị hỏng trên trang web của tôi sau khi nâng cấp lên PHP 7 Uncaught Error: [] operator not supported for stringsgây ra lỗi vì bản gốc meta_queryđã trở lại là null. Bạn có thể khắc phục nó bằng cách té ngửa ra một mảng rỗng nếu không tồn tại chuyển ra $meta_query = $query->get('meta_query');cho $meta_query = ( is_array( $query->get('meta_query') ) ) ? $query->get('meta_query') : [];.
Kevin Nugent

2

Tôi muốn đăng giải pháp tạm thời của mình cho các bài đăng nổi bật trong trường hợp một số người có thể sử dụng nó. Tôi không sử dụng pre_get_postshook ở đây nhưng cũng không query_posts. Vấn đề là tôi phải chơi với truy vấn chính và phải chạy một đoạn truy vấn sql. Tôi sẽ rất vui nếu bất kỳ chuyên gia nào có thể kiểm tra mã và cho tôi biết liệu nó có ổn không và sẽ không gây ra bất kỳ vấn đề nào về hiệu suất. Nó cũng sẽ là tuyệt vời nếu bất cứ ai có một cách tiếp cận tốt hơn và chia sẻ nó với chúng tôi.

Tạo truy vấn bài viết nổi bật

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

?>

Tạo truy vấn chính, loại trừ các bài đăng có meta_key nổi bật, giới hạn loại trừ ở 5 bài đăng gần đây nhất và hiển thị tất cả các bài đăng khác.

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

Trong phản hồi @Carleway, nếu bạn muốn loại trừ 5 bài đăng gần đây nhất được đánh dấu đặc trưng, ​​bạn có thể làm như sau. Thay đổi post_per_page thành số lượng bạn muốn loại trừ và meta_query thành cách bạn chỉ định danh mục nổi bật.

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' );
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.