कस्टम छोरों के लिए पृष्ठांकन कैसे ठीक करें?


122

मैंने एक टेम्पलेट फ़ाइल / कस्टम पेज टेम्पलेट में एक कस्टम / माध्यमिक क्वेरी जोड़ा है; मैं मुख्य क्वेरी लूप के पृष्ठांकन का उपयोग करने के बजाय वर्डप्रेस को पृष्ठांकन के लिए अपनी कस्टम क्वेरी का उपयोग कैसे कर सकता हूं?

परिशिष्ट

मैंने के माध्यम से मुख्य लूप क्वेरी को संशोधित किया है query_posts()। पेजिंग काम क्यों नहीं कर रहा है, और मैं इसे कैसे ठीक करूं?

जवाबों:


215

समस्या

डिफ़ॉल्ट रूप से, किसी भी संदर्भ में, वर्डप्रेस पेजिनेशन निर्धारित करने के लिए मुख्य क्वेरी का उपयोग करता है। मुख्य क्वेरी ऑब्जेक्ट को $wp_queryवैश्विक में संग्रहीत किया जाता है , जिसका उपयोग मुख्य क्वेरी लूप को आउटपुट करने के लिए भी किया जाता है:

if ( have_posts() ) : while ( have_posts() ) : the_post();

जब आप एक कस्टम क्वेरी का उपयोग करते हैं , तो आप एक बिलकुल अलग क्वेरी ऑब्जेक्ट बनाते हैं:

$custom_query = new WP_Query( $custom_query_args );

और यह क्वेरी पूरी तरह से अलग लूप के माध्यम से आउटपुट है:

if ( $custom_query->have_posts() ) : 
    while ( $custom_query->have_posts() ) : 
        $custom_query->the_post();

लेकिन सहित पृष्ठांकन टेम्पलेट टैग, previous_posts_link(), next_posts_link(), posts_nav_link(), और paginate_links(), पर उनके उत्पादन का आधार मुख्य क्वेरी वस्तु , $wp_query। वह मुख्य क्वेरी पृष्ठबद्ध नहीं हो सकती है या नहीं। यदि वर्तमान संदर्भ एक कस्टम पेज टेम्प्लेट है, उदाहरण के लिए, मुख्य $wp_queryऑब्जेक्ट में केवल एक ही पोस्ट शामिल होगी - उस पेज की आईडी की जिसमें कस्टम पेज टेम्प्लेट असाइन किया गया है।

यदि वर्तमान संदर्भ किसी प्रकार का संग्रह अनुक्रमणिका है, तो मुख्य में $wp_queryपेजेशन करने के लिए पर्याप्त पद शामिल हो सकते हैं, जो समस्या के अगले भाग की ओर जाता है: मुख्य $wp_queryवस्तु के लिए, वर्डप्रेस paged क्वेरी के आधार पर एक पैरामीटर पारित करेगा । pagedURL क्वेरी चर। जब क्वेरी प्राप्त होती है, तो उस pagedपैरामीटर का उपयोग यह निर्धारित करने के लिए किया जाएगा कि कौन से पृष्ठ पर वापस जाने के लिए पृष्ठांकित पदों का सेट है। यदि एक प्रदर्शित पृष्ठांकन लिंक पर क्लिक किया जाता है, और अगले पृष्ठ को लोड किया जाता है, तो आपके कस्टम क्वेरी के पास यह जानने का कोई तरीका नहीं होगा कि पृष्ठांकन बदल गया है

समाधान

कस्टम क्वेरी में सही पृष्ठांकित पासिंग

यह मानते हुए कि कस्टम क्वेरी एक आर्ग्स सरणी का उपयोग करती है:

$custom_query_args = array(
    // Custom query parameters go here
);

आपको pagedसरणी के लिए सही पैरामीटर पास करना होगा । आप वर्तमान पृष्ठ को निर्धारित करने के लिए उपयोग किए गए URL क्वेरी चर को प्राप्त करके ऐसा कर सकते हैं get_query_var():

get_query_var( 'paged' );

फिर आप उस पैरामीटर को अपनी कस्टम क्वेरी args सरणी में जोड़ सकते हैं:

$custom_query_args['paged'] = get_query_var( 'paged' ) 
    ? get_query_var( 'paged' ) 
    : 1;

नोट: यदि आपका पृष्ठ एक स्थिर फ्रंट पेज है , तो pageइसके बजाय pagedएक स्थिर फ्रंट पेज का उपयोग करना pageऔर न करना सुनिश्चित करें paged। यह वही है जो आपके पास स्थिर फ्रंट पेज के लिए होना चाहिए

$custom_query_args['paged'] = get_query_var( 'page' ) 
    ? get_query_var( 'page' ) 
    : 1;

अब, जब कस्टम क्वेरी प्राप्त होती है, तो पृष्ठांकित पदों का सही सेट वापस आ जाएगा।

पेजेशन फंक्शंस के लिए कस्टम क्वेरी ऑब्जेक्ट का उपयोग करना

पृष्ठांकन फ़ंक्शन के लिए सही आउटपुट प्राप्त करने के लिए - यानी कस्टम क्वेरी के सापेक्ष पिछले / अगले / पृष्ठ लिंक - वर्डप्रेस को कस्टम क्वेरी को पहचानने के लिए मजबूर करने की आवश्यकता है। इसके लिए "हैक" की आवश्यकता है: $wp_queryकस्टम ऑब्जेक्ट ऑब्जेक्ट के साथ मुख्य ऑब्जेक्ट को प्रतिस्थापित करना $custom_query:

मुख्य क्वेरी ऑब्जेक्ट को हैक करें

  1. मुख्य क्वेरी ऑब्जेक्ट का बैकअप लें: $temp_query = $wp_query
  2. मुख्य क्वेरी ऑब्जेक्ट को नल करें: $wp_query = NULL;
  3. कस्टम क्वेरी को मुख्य क्वेरी ऑब्जेक्ट में स्वैप करें: $wp_query = $custom_query;

    $temp_query = $wp_query;
    $wp_query   = NULL;
    $wp_query   = $custom_query;
    

यह "हैक" किसी भी पेजिंग फ़ंक्शन को कॉल करने से पहले किया जाना चाहिए

मुख्य क्वेरी ऑब्जेक्ट को रीसेट करें

एक बार पृष्ठांकन फ़ंक्शन आउटपुट होने के बाद, मुख्य क्वेरी ऑब्जेक्ट रीसेट करें:

$wp_query = NULL;
$wp_query = $temp_query;

पृष्ठ पर अंक लगाना फ़िक्स ठीक करता है

previous_posts_link()सामान्य रूप से कार्य, पृष्ठांकन की परवाह किए बिना काम करेंगे। यह केवल वर्तमान पृष्ठ को निर्धारित करता है, और उसके लिए लिंक को आउटपुट करता है page - 1। हालांकि, ठीक next_posts_link()से आउटपुट के लिए एक फिक्स की आवश्यकता होती है। ऐसा इसलिए है क्योंकि पैरामीटर next_posts_link()का उपयोग करता है max_num_pages:

<?php next_posts_link( $label , $max_pages ); ?>

अन्य क्वेरी मापदंडों के साथ, डिफ़ॉल्ट रूप से फ़ंक्शन max_num_pagesमुख्य $wp_queryऑब्जेक्ट के लिए उपयोग करेगा । ऑब्जेक्ट के next_posts_link()लिए मजबूर करने के लिए $custom_query, आपको max_num_pagesफ़ंक्शन को पास करना होगा । आप इस मान को $custom_queryऑब्जेक्ट से प्राप्त कर सकते हैं $custom_query->max_num_pages:

<?php next_posts_link( 'Older Posts' , $custom_query->max_num_pages ); ?>

यह सब एक साथ डालें

निम्नलिखित ठीक से काम करने वाले फंक्शन के साथ कस्टम क्वेरी लूप का एक बुनियादी निर्माण है:

// Define custom query parameters
$custom_query_args = array( /* Parameters go here */ );

// Get current page and append to custom query parameters array
$custom_query_args['paged'] = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;

// Instantiate custom query
$custom_query = new WP_Query( $custom_query_args );

// Pagination fix
$temp_query = $wp_query;
$wp_query   = NULL;
$wp_query   = $custom_query;

// Output custom query loop
if ( $custom_query->have_posts() ) :
    while ( $custom_query->have_posts() ) :
        $custom_query->the_post();
        // Loop output goes here
    endwhile;
endif;
// Reset postdata
wp_reset_postdata();

// Custom query loop pagination
previous_posts_link( 'Older Posts' );
next_posts_link( 'Newer Posts', $custom_query->max_num_pages );

// Reset main query object
$wp_query = NULL;
$wp_query = $temp_query;

परिशिष्ट: क्या बारे में query_posts()?

query_posts() माध्यमिक छोरों के लिए

यदि आप query_posts()एक कस्टम लूप का उत्पादन करने के लिए उपयोग कर रहे हैं , बल्कि तब के माध्यम से कस्टम क्वेरी के लिए एक अलग ऑब्जेक्ट को इंस्टेंट WP_Query()कर रहे हैं _doing_it_wrong(), तो आप कर रहे हैं , और कई समस्याओं में भाग लेंगे ( जिनमें से कम से कम अंकन मुद्दे होंगे)। उन मुद्दों को हल करने के लिए पहला कदम query_posts()उचित WP_Query()कॉल के अनुचित उपयोग को परिवर्तित करना होगा ।

query_posts()मुख्य लूप को संशोधित करने के लिए उपयोग करना

यदि आप केवल मुख्य लूप क्वेरी के लिए मापदंडों को संशोधित करना चाहते हैं - जैसे कि प्रति पृष्ठ पदों को बदलना, या एक श्रेणी को छोड़कर - आपको उपयोग करने के लिए परीक्षा हो सकती है query_posts()। लेकिन आप अभी भी नहीं करना चाहिए। जब आप उपयोग करते हैं query_posts(), तो आप वर्डप्रेस को मुख्य क्वेरी ऑब्जेक्ट को बदलने के लिए मजबूर करते हैं। (वर्डप्रेस वास्तव में एक दूसरी क्वेरी बनाता है, और ओवरराइट करता है $wp_query।) समस्या यह है कि, यह इस प्रतिस्थापन को इस प्रक्रिया में बहुत देर से करता है ताकि पृष्ठांकन अपडेट किया जा सके।

समाधान मुख्य प्रश्न को फ़िल्टर करने से पहले है पोस्ट कोpre_get_posts हुक के माध्यम से लाया जाता है

श्रेणी टेम्पलेट फ़ाइल में इसे जोड़ने के बजाय ( category.php):

query_posts( array(
    'posts_per_page' => 5
) );

निम्नलिखित को इसमें जोड़ें functions.php:

function wpse120407_pre_get_posts( $query ) {
    // Test for category archive index
    // and ensure that the query is the main query
    // and not a secondary query (such as a nav menu
    // or recent posts widget output, etc.
    if ( is_category() && $query->is_main_query() ) {
        // Modify posts per page
        $query->set( 'posts_per_page', 5 ); 
    }
}
add_action( 'pre_get_posts', 'wpse120407_pre_get_posts' );

इसे ब्लॉग पोस्ट इंडेक्स टेम्प्लेट फ़ाइल में जोड़ने के बजाय ( home.php):

query_posts( array(
    'cat' => '-5'
) );

निम्नलिखित को इसमें जोड़ें functions.php:

function wpse120407_pre_get_posts( $query ) {
    // Test for main blog posts index
    // and ensure that the query is the main query
    // and not a secondary query (such as a nav menu
    // or recent posts widget output, etc.
    if ( is_home() && $query->is_main_query() ) {
        // Exclude category ID 5
        $query->set( 'category__not_in', array( 5 ) ); 
    }
}
add_action( 'pre_get_posts', 'wpse120407_pre_get_posts' );

इस तरह, वर्डप्रेस पहले से ही संशोधित $wp_queryऑब्जेक्ट का उपयोग करेगा जब पेजिंग का निर्धारण किया जाएगा, जिसमें कोई टेम्पलेट संशोधन की आवश्यकता नहीं होगी।

कब किस फंक्शन का इस्तेमाल करें

अनुसंधान इस सवाल-जवाब और इस सवाल-जवाब समझने के लिए कैसे और कब उपयोग करने के लिए WP_Query, pre_get_postsऔर query_posts()


31
कोडेक्स में विश पेज इतने पूरे हो सकते हैं।
पीटर गोएन

चिप, आपने मेरा दिन बना दिया!
tepkenvannkorn

1
चिप, आप हमेशा इतना समय बचाते हैं! अगर मैं पागल होने से पहले केवल Google आपको उच्चतर उत्तर देगा (googlers के लिए कॉलआउट), धन्यवाद।
सगिव एसईओ

आपके उदाहरण का उपयोग करते हुए मैं काम करने के लिए पेजिंग नहीं प्राप्त कर सकता था जब तक कि मैं इस पृष्ठ के नीचे मध्य-मार्ग (जैसे:? सशर्त) पाया गया एक और ब्लॉक का उपयोग नहीं करता था: themeforest.net/forums/thread/… , बहुत अजीब। अन्यथा इस जवाब ने मुझे बहुत कुछ सिखाया।
पी औल

2
शानदार जवाब - 1 बात, मुझे अजाक्स कॉल में अगले / पिछले पोस्ट लिंक फ़ंक्शन को चलाने में समस्या हो रही थी - यह बस नहीं लगेगा - चारों ओर एक त्वरित खुदाई के बाद मैंने पाया कि वैश्विक pagedअपडेट नहीं किया जा रहा था (एडमिन के साथ कुछ करने के लिए- ajax.php पर्यावरण) इसलिए मैंने global $paged; $paged = $custom_query_args['paged']; इसे जोड़ा: और इसने काम किया :)
acSlater

21

मैं पेजिनेशन के साथ कस्टम लूप के लिए इस कोड का उपयोग करता हूं:

<?php
if ( get_query_var('paged') ) {
    $paged = get_query_var('paged');
} elseif ( get_query_var('page') ) { // 'page' is used instead of 'paged' on Static Front Page
    $paged = get_query_var('page');
} else {
    $paged = 1;
}

$custom_query_args = array(
    'post_type' => 'post', 
    'posts_per_page' => get_option('posts_per_page'),
    'paged' => $paged,
    'post_status' => 'publish',
    'ignore_sticky_posts' => true,
    //'category_name' => 'custom-cat',
    'order' => 'DESC', // 'ASC'
    'orderby' => 'date' // modified | title | name | ID | rand
);
$custom_query = new WP_Query( $custom_query_args );

if ( $custom_query->have_posts() ) :
    while( $custom_query->have_posts() ) : $custom_query->the_post(); ?>

        <article <?php post_class(); ?>>
            <h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
            <small><?php the_time('F jS, Y') ?> by <?php the_author_posts_link() ?></small>
            <div><?php the_excerpt(); ?></div>
        </article>

    <?php
    endwhile;
    ?>

    <?php if ($custom_query->max_num_pages > 1) : // custom pagination  ?>
        <?php
        $orig_query = $wp_query; // fix for pagination to work
        $wp_query = $custom_query;
        ?>
        <nav class="prev-next-posts">
            <div class="prev-posts-link">
                <?php echo get_next_posts_link( 'Older Entries', $custom_query->max_num_pages ); ?>
            </div>
            <div class="next-posts-link">
                <?php echo get_previous_posts_link( 'Newer Entries' ); ?>
            </div>
        </nav>
        <?php
        $wp_query = $orig_query; // fix for pagination to work
        ?>
    <?php endif; ?>

<?php
    wp_reset_postdata(); // reset the query 
else:
    echo '<p>'.__('Sorry, no posts matched your criteria.').'</p>';
endif;
?>

स्रोत:


1
इस उत्तर के एक प्रकार के साथ एक और अच्छा ट्यूटोरियल: callmenick.com/post/custom-wordpress-loop-with-pagination
mrwweb

5

हमेशा की तरह चिप। इसके लिए एक परिशिष्ट के रूप में, उस स्थिति पर विचार करें जिसके तहत आप किसी "इंट्रो टेक्स्ट" के लिए पेज से जुड़े एक वैश्विक पेज टेम्पलेट का उपयोग कर रहे हैं और इसके बाद एक उपशम है जिसे आप पृष्ठांकित करना चाहते हैं।

पगति_लिंक () का उपयोग करते हुए जैसा कि आप ऊपर उल्लेख करते हैं, अधिकतर चूक के साथ, (और यह मानते हुए कि आपके पास बहुत अधिक पर्मलिंक्स हैं) आपके पृष्ठभाग लिंक डिफ़ॉल्ट होंगे mysite.ca/page-slug/page/#जो कि सुंदर हैं, लेकिन 404त्रुटियां फेंक देंगे क्योंकि वर्डप्रेस उस विशेष URL संरचना के बारे में नहीं जानता है और वास्तव में होगा "पृष्ठ" का एक बच्चा पृष्ठ देखें जो "पृष्ठ-स्लग" का बच्चा हो।

यहाँ ट्रिक एक निफ्टी रीराइट नियम को सम्मिलित करने के लिए है जो केवल उस विशेष "छद्म संग्रह पृष्ठ" पृष्ठ पर लागू होता है, जो उस ढलान को स्वीकार करता है जो /page/#/संरचना को स्वीकार करता है और इसे एक क्वेरी स्ट्रिंग में फिर से लिखता है जिसे वर्डप्रेस समझ सकता है, अर्थात् mysite.ca/?pagename=page-slug&paged=#। नोट pagenameऔर pagedनहीं nameऔर page(जो मुझे वजह से सचमुच दु: ख के घंटे, यहाँ इस जवाब को प्रेरित!)।

यहां पुनर्निर्देशित नियम है:

add_rewrite_rule( "page-slug/page/([0-9]{1,})/?$", 'index.php?pagename=page-slug&paged=$matches[1]', "top" );

हमेशा की तरह, जब नियमों को फिर से लिखना हो, तो बैक-एंड में Settings> Permalinks पर जाकर अपने Permalinks को फ्लश करना याद रखें ।

यदि आपके पास कई पृष्ठ हैं जो इस तरह से व्यवहार करने जा रहे हैं (उदाहरण के लिए, जब कई कस्टम पोस्ट प्रकारों के साथ काम करते हैं), तो आप प्रत्येक पृष्ठ स्लग के लिए एक नया पुनर्लेखन नियम बनाने से बचना चाह सकते हैं। हम एक अधिक सामान्य नियमित अभिव्यक्ति लिख सकते हैं जो आपके द्वारा पहचाने गए किसी भी पृष्ठ स्लग के लिए काम करती है।

एक दृष्टिकोण नीचे है:

function wpse_120407_pseudo_archive_rewrite(){
    // Add the slugs of the pages that are using a Global Template to simulate being an "archive" page
    $pseudo_archive_pages = array(
        "all-movies",
        "all-actors"
    );

    $slug_clause = implode( "|", $pseudo_archive_pages );
    add_rewrite_rule( "($slug_clause)/page/([0-9]{1,})/?$", 'index.php?pagename=$matches[1]&paged=$matches[2]', "top" );
}
add_action( 'init', 'wpse_120407_pseudo_archive_rewrite' );

नुकसान / कैविट्स

इस दृष्टिकोण का एक नुकसान जो मुझे अपने मुंह में थपथपाता है, वह पेज स्लग का हार्ड-कोडिंग है। यदि कोई व्यवस्थापक कभी भी उस छद्म-संग्रह पृष्ठ के पृष्ठ स्लग को बदलता है, तो आप टोस्ट करते हैं - पुनर्लेखन नियम अब मेल नहीं खाएगा और आपको खतरनाक 404 मिलेगा।

मुझे यकीन नहीं है कि मैं इस पद्धति के लिए एक वर्कअराउंड के बारे में सोच सकता हूं, लेकिन यह अच्छा होगा यदि यह वैश्विक पेज टेम्पलेट है जो किसी भी तरह से फिर से लिखे गए नियम को ट्रिगर करता है। किसी दिन मैं इस जवाब पर फिर से विचार कर सकता हूं अगर किसी और ने उस विशेष अखरोट को नहीं तोड़ा हो।


1
आप पोस्ट को सहेजने के लिए हुक कर सकते हैं, जांच सकते हैं कि क्या पेज में मेटा कुंजी के तहत आपका आर्काइव टेम्प्लेट है _wp_page_template, तो एक और रीराइट और फ्लश नियम जोड़ें।
मिलो

2

मैंने के माध्यम से मुख्य लूप क्वेरी को संशोधित किया है query_posts()। पेजिंग काम क्यों नहीं कर रहा है, और मैं इसे कैसे ठीक करूं?

महान जवाब चिप बनाया आज संशोधित करने की जरूरत है।
कुछ समय के लिए हमारे पास $wp_the_queryवैरिएबल है जो $wp_queryमुख्य क्वेरी निष्पादित होने के ठीक बाद वैश्विक के बराबर होना चाहिए ।

यही कारण है कि यह चिप के जवाब से हिस्सा है:

मुख्य क्वेरी ऑब्जेक्ट को हैक करें

अब जरूरत नहीं है। हम अस्थायी चर बनाने के साथ इस हिस्से को भूल सकते हैं।

// Pagination fix
$temp_query = $wp_query;
$wp_query   = NULL;
$wp_query   = $custom_query;

तो अब हम कॉल कर सकते हैं:

$wp_query   = $wp_the_query;

या इससे भी बेहतर हम कॉल कर सकते हैं:

wp_reset_query();

सब कुछ चिप उल्लिखित रहता है। उस क्वेरी-रीसेट-पार्ट के बाद आप पेजेशन फ़ंक्शन को कॉल कर सकते हैं जो हैं f($wp_query), - वे $wp_queryवैश्विक पर निर्भर करते हैं ।


फ़ागिनेशन मैकेनिक को और बेहतर बनाने और query_postsफ़ंक्शन को और अधिक स्वतंत्रता देने के लिए मैंने यह संभव सुधार बनाया:

https://core.trac.wordpress.org/ticket/39483


1
global $wp_query;
        $paged = get_query_var('paged', 1);

    $args = array( 
        'post_type' => '{your_post_type_name}',
        'meta_query' => array('{add your meta query argument if need}'),  
        'orderby' => 'modified',
        'order' => 'DESC',
        'posts_per_page' => 20,
        'paged' => $paged 
    );
    $query = new WP_Query($args);

    if($query->have_posts()):
        while ($query->have_posts()) : $query->the_post();
            //add your code here
        endwhile;
        wp_reset_query();

        //manage pagination based on custom Query.
        $GLOBALS['wp_query']->max_num_pages = $query->max_num_pages;
        the_posts_pagination(array(
            'mid_size' => 1,
            'prev_text' => __('Previous page', 'patelextensions'),
            'next_text' => __('Next page', 'patelextensions'),
            'before_page_number' => '<span class="meta-nav screen-reader-text">' . __('Page', 'patelextensions') . ' </span>',
        ));
    else:
    ?>
        <div class="container text-center"><?php echo _d('Result not found','30'); ?></div>
    <?php
        endif;
    ?>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.