the_content và is_main_query


15

Tôi đang lọc nội dung với the_contentbộ lọc. Mọi thứ đều hoạt động hoàn hảo, trích dẫn rằng những thay đổi của tôi cũng được áp dụng cho các truy vấn tùy chỉnh. Các thay đổi của tôi cũng xuất hiện trong thanh bên nếu tiện ích sử dụng truy vấn tùy chỉnh

Để chống lại điều đó, tôi đang sử dụng is_main_query()để chỉ nhắm mục tiêu truy vấn chính, nhưng nó không hoạt động. Thay đổi chỉ đơn giản là vẫn được áp dụng cho tất cả các truy vấn thông qua. Mặc dù điều này thật buồn cười, tất cả các kiểm tra có điều kiện khác đều thích is_single()is_category()đang hoạt động nếu tôi nhắm mục tiêu các trang cụ thể, ngoại trừ tất cả các thay đổi ảnh hưởng đến bất kỳ truy vấn tùy chỉnh nào khác trên trang đó, cho dù tôi có sử dụng is_main_query()hay không

Am i thiếu cái gì ở đây. Làm cách nào để áp dụng các thay đổi của tôi cho truy vấn chính chỉ bằng the_contentbộ lọc

add_filter('the_content', 'custom_content');

function custom_content($content){

    if(is_main_query()){ // << THIS IS NOT WORKING
        // My custom content that I add to the_content()    
    }
    return $content;
}

Câu trả lời:


11

Thành thật mà nói, chức năng in_the_loop()là những gì bạn đang tìm kiếm:

add_filter( 'the_content', 'custom_content' );

function custom_content( $content ) {
    if ( in_the_loop() ) {
        // My custom content that I add to the_content()    
    }
    return $content;
}

Điều gì in_the_looplàm là kiểm tra xem toàn cầu cho $wp_query(đó là đối tượng truy vấn chính) của bài đăng hiện tại là -1 < $current_post < $post_count.

Điều đó xảy ra khi truy vấn chính được lặp, bởi vì trước khi vòng lặp bắt đầu, bài đăng hiện tại là -1 và sau khi vòng lặp kết thúc, bài đăng hiện tại được đặt lại thành -1.

Vì vậy, nếu in_the_loop()là đúng, điều đó có nghĩa là đối tượng truy vấn chính đang lặp, đây là điều bạn cần trong trường hợp này (và là kết quả tương tự của việc thêm loop_startvà xóa hành động loop_end, như câu trả lời @ialocin đã viết; thực tế nó hoạt động với cùng lý do và có +1 của tôi.

Lợi ích của cách tiếp cận @ ialocin là khi bạn muốn nhắm mục tiêu một đối tượng truy vấn khác với đối tượng chính, vì in_the_loop()chỉ hoạt động cho truy vấn chính.


Trong tất cả các tìm kiếm trang web của tôi hoặc tìm kiếm trực tuyến tôi đã đi qua điều này. Một viên ngọc ẩn mà hoạt động. Mọi giải pháp sử dụng is_main_query, thực sự nghĩ rằng không ai kiểm tra điều này kỹ lưỡng. Cảm ơn bạn đã đóng góp, thực sự đánh giá cao
Pieter Goosen

1
@PieterGoosen Vui mừng khi nó hoạt động. Đó là một chức năng rất cũ, xuất hiện từ thời is_main_querykhông phải là một thứ.
gmazzap

Bạn thấy đấy, đây là nơi tôi đã bỏ lỡ nó, tôi không phải là một bộ đếm thời gian cũ :-), đã tham gia Wordpress trong 3.3.
Pieter Goosen

2
@GM bạn có phiền khi thêm điều này vào câu trả lời của bạn. Đây là thông tin hữu ích cho những người khác có thể vấp phải câu trả lời này. Hầu hết mọi người, như tôi, không đọc bình luận :-)
Pieter Goosen

1
@PieterGoosen xong :)
gmazzap

7

Đây chỉ là một bổ sung cho câu trả lời của @ Otto. Chỉ để làm cho nó tốt hơn một chút dễ hiểu. Về cơ bản những gì @Otto đang nói, bạn phải đảo ngược logic, điều đó có nghĩa là: nếu bạn có thể xác định một cách đáng tin cậy truy vấn chính, thì bạn có thể thêm - và xóa - kết nối của bạn vào the_contentbộ lọc.

Ví dụ: truy vấn chính có thể được nhận ra một cách đáng tin cậy tại pre_get_postshành động, vì vậy điều này sẽ hoạt động:

function wpse162747_the_content_filter_callback( $content ) {
    return $content . 'with something appended';
}

add_action( 'pre_get_posts', 'wpse162747_pre_get_posts_callback' );
function wpse162747_pre_get_posts_callback( $query ) {
    if ( $query->is_main_query() ) {
        add_filter( 'the_content', 'wpse162747_the_content_filter_callback' );
    }
}

Vì bạn phải loại bỏ bộ lọc khi không còn cần thiết, tôi nghĩ rằng loop_endhành động này sẽ là một nơi tốt cho điều đó và là đối tác của nó, chúng ta có thể sử dụng loop_start. Mà sẽ trông như thế này:

add_action( 'loop_start', 'wpse162747_loop_start_callback' );
function wpse162747_loop_start_callback( $query ) {
    if ( $query->is_main_query() ) {
        add_filter( 'the_content', 'wpse162747_the_content_filter_callback' );
    }
}

add_action( 'loop_end', 'wpse162747_loop_end_callback' );
function wpse162747_loop_end_callback( $query ) {
    if ( $query->is_main_query() ) {
        remove_filter( 'the_content', 'wpse162747_the_content_filter_callback' );
    }
}

Sẽ kiểm tra tommorow này. Cảm ơn bạn đã giải thích chi tiết.
Pieter Goosen

Niềm vui của tôi như mọi khi @PieterGoosen Đừng vội vàng, nhưng hãy làm điều đó, bởi vì tôi chưa - ít nhất là không đủ.
Nicolai

1
Điều gì xảy ra nếu một shortcode được sử dụng trong the_content () và shortcode bắt đầu một truy vấn khác gọi the_content (), đặt lại đối tượng bài hiện tại và vòng lặp tiếp tục? Tất cả các bộ lọc sẽ được áp dụng. Khá khó khăn ở đây, không được lưu trong chuông in_the_loop () ... Đó là lý do tại sao tôi đề xuất, luôn xóa các bộ lọc độc đáo ngay khi chúng được thực hiện, như được tiếp cận bởi @Nicolai
Jonas Lundman

5

Bạn đang sử dụng is_main_query()không chính xác. Hàm is_main_query () toàn cầu trả về true trừ khi biến $ wp_query toàn cầu đã được xác định lại.

Có lẽ không có cách nào đáng tin cậy 100% để nói, từ bên trong bộ lọc_content, cho dù Vòng lặp hiện tại bạn có là truy vấn chính hay không. Bộ lọc nội dung chỉ lọc nội dung. Nó không có bất kỳ hình thức khả năng nào để biết nó đang được sử dụng cho vòng lặp nào.

Thay vào đó, bạn nên thêm bộ lọc của mình khi bạn cần, sau đó xóa nó khi bạn không.


Đây thực sự là một sự thất vọng khi không có phương tiện nào để nhắm mục tiêu truy vấn chính bằng the_contentbộ lọc
Pieter Goosen

Chà, điều đó thực sự không đáng ngạc nhiên. Giống như bất kỳ bộ lọc khác, nó chỉ lọc mọi thứ. Nó không biết bối cảnh xung quanh khi nó được gọi. Nó thậm chí có thể không được gọi từ bên trong một Vòng lặp thích hợp. Không có cách nào để nó nói.
Otto
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.