the_content dan is_main_query

15

Saya memfilter konten dengan the_contentfilter. Semuanya berfungsi dengan sempurna, petikan bahwa perubahan saya juga diterapkan pada permintaan khusus. Perubahan saya juga muncul di bilah sisi jika widget menggunakan kueri khusus

Untuk mengatasinya, saya menggunakan hanya is_main_query()menargetkan permintaan utama, tetapi tidak berfungsi. Perubahan hanya masih diterapkan untuk semua permintaan sepanjang. Apa yang lucu, semua pemeriksaan bersyarat lainnya suka is_single()dan is_category()berfungsi jika saya menargetkan halaman tertentu, kecuali bahwa semua perubahan memengaruhi kueri khusus lainnya pada halaman itu, apakah saya menggunakan is_main_query()atau tidak

Apakah saya melewatkan sesuatu di sini. Bagaimana cara menerapkan perubahan saya ke permintaan utama hanya menggunakan the_contentfilter

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;
}
Pieter Goosen
sumber

Jawaban:

11

Jujur saja, fungsinya in_the_loop()adalah apa yang Anda cari:

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

Apa yang in_the_loopdilakukan adalah memeriksa apakah global untuk $wp_query(itu adalah objek permintaan utama) dari posting saat ini -1 < $current_post < $post_count.

Itu terjadi ketika kueri utama adalah perulangan, karena sebelum perulangan dimulai, pos saat ini adalah -1, dan setelah perulangan berakhir, pos saat ini diatur ulang ke -1 lagi.

Jadi, jika in_the_loop()benar, itu berarti bahwa objek kueri utama adalah perulangan, yang merupakan apa yang Anda butuhkan dalam kasus ini (dan merupakan hasil yang sama dari menambahkan tindakan pada loop_startdan menghapus loop_end, seperti jawaban yang ditulis @ialocin; pada kenyataannya ia berfungsi; untuk alasan yang sama, dan mendapat +1 saya).

Manfaat dari pendekatan @ialocin adalah ketika Anda ingin menargetkan objek permintaan yang berbeda dari yang utama, karena in_the_loop()hanya berfungsi untuk permintaan utama.

gmazzap
sumber
Tidak ada pencarian situs saya atau pencarian online saya menemukan ini. Permata tersembunyi yang berfungsi. Setiap solusi menggunakan is_main_query, benar-benar berpikir tidak ada yang menguji ini secara menyeluruh. Terima kasih atas masukan Anda, sangat dihargai
Pieter Goosen
1
@PieterGoosen Senang itu berfungsi. Itu adalah fungsi yang sangat lama, datang langsung dari saat-saat ketika is_main_queryitu bukan suatu hal.
gmazzap
Anda lihat, di sinilah saya melewatkannya, saya bukan timer lama :-), bergabung dengan Wordpress di 3.3.
Pieter Goosen
2
@GM maukah Anda menambahkan ini ke jawaban Anda. Ini adalah info berguna untuk orang lain yang mungkin menemukan jawaban ini. Kebanyakan orang, seperti saya, tidak membaca komentar :-)
Pieter Goosen
1
@PieterGoosen selesai :)
gmazzap
7

Ini hanyalah tambahan untuk jawaban @ Otto. Hanya agar sedikit lebih baik dimengerti. Pada dasarnya apa yang dikatakan @Otto, Anda harus membalikkan logikanya, yang berarti: jika Anda dapat menentukan permintaan utama dengan andal, maka Anda dapat menambahkan - dan menghapus - kaitan Anda ke dalam the_contentfilter.

Misalnya kueri utama dapat dikenali saat pre_get_postsaksi, jadi ini akan bekerja:

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

Karena Anda seharusnya menghapus filter ketika tidak lagi diperlukan, saya pikir loop_endtindakan harus menjadi tempat yang baik untuk itu dan sebagai mitra kami dapat digunakan loop_start. Yang akan terlihat seperti ini:

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' );
    }
}
Nicolai
sumber
Akan menguji besok ini. Terima kasih atas penjelasan terperinci Anda.
Pieter Goosen
Kesenangan saya seperti biasa @PieterGoosen Tidak terburu-buru, tapi lakukanlah, karena saya belum - setidaknya tidak cukup.
Nicolai
1
Bagaimana jika kode pendek digunakan di dalam konten_ () dan kode pendek memulai permintaan lain yang memanggil konten_ (), reset objek posting saat ini dan loop terus? Semua filter akan berlaku. Cukup rumit di sini, tidak diselamatkan oleh bel in_the_loop () ... Itulah sebabnya saya sarankan, untuk selalu menghapus filter unik segera setelah selesai, seperti didekati oleh @Nicolai
Jonas Lundman
5

Anda menggunakan is_main_query()salah. Fungsi global is_main_query () mengembalikan true kecuali variabel global $ wp_query telah didefinisikan ulang.

Mungkin tidak ada 100% cara andal untuk mengetahui, dari dalam filter the_content, apakah Loop saat ini yang Anda gunakan adalah pertanyaan utama atau tidak. Filter konten hanya menyaring konten. Itu tidak memiliki segala bentuk kemampuan untuk mengetahui untuk apa loop itu digunakan.

Alih-alih, Anda harus menambahkan filter saat dibutuhkan, lalu hapus ketika tidak diperlukan.

Otto
sumber
Sebenarnya ini adalah kekecewaan bahwa tidak ada sarana straighforward untuk menargetkan kueri utama dengan the_contentfilter
Pieter Goosen
Yah, itu sebenarnya tidak mengejutkan. Seperti filter lainnya, filter hanya menyaring beberapa hal. Itu tidak tahu konteks sekitarnya ketika sedang dipanggil. Bahkan mungkin tidak dipanggil dari dalam Loop yang tepat. Tidak mungkin untuk mengatakannya.
Otto