Как исправить нумерацию страниц для пользовательских циклов?

Я добавил пользовательский (дополнительный) запрос к файлу шаблона (шаблона пользовательской страницы). Как заставить WordPress использовать мой пользовательский запрос для разбивки на страницы вместо использования нумерации в основном цикле?

Добавлено

Я изменил запрос основного цикла через query_posts(). Почему не работает разбиение на страницы, и как мне это исправить?

Понравилась статья? Поделиться с друзьями:
WPAsk
Ответов: 5
  1. ravi patel
    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();
                //ваш код
            endwhile;
            wp_reset_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;
        ?>
    
  2. Chip Bennett

    Проблема

    По умолчанию в любом данном контексте WordPress использует основной запрос для определения нумерации страниц. Основной объект запроса хранится в глобальном $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(), базируются на основном объекте запроса main query object, $wp_query. Этот основной запрос может быть или не быть разбит на страницы. Например, если текущий контекст представляет собой пользовательский шаблон страницы, основной объект $wp_query будет состоять только из одного сообщения — идентификатора страницы, которой назначен пользовательскому шаблону страницы.

    Если текущий контекст является каким-либо архивным индексом, основной $wp_query может состоять из достаточного количества сообщений, чтобы вызвать разбиение на страницы, что приводит к следующей части проблемы: для основного $wp_query Объект , WordPress передает в запрос параметр paged , основанный на переменной запроса URL paged . Когда запрос извлекается, этот параметр paged будет использоваться для определения того, какой набор постраничных постов должен возвращаться. Если щелкнуть на отображаемую ссылку нумерации страниц и загрузить следующую страницу, ваш пользовательский запрос не сможет узнать, что нумерация страниц изменилась .

    Решение

    Передача правильного постраничного параметра в пользовательский запрос

    Предполагая, что пользовательский запрос использует массив args:

    $custom_query_args = array(
        // Пользовательские параметры запроса
    );
    

    Вам нужно будет передать в массив правильный параметр 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 в качестве статической главной страницы.

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

    Теперь при получении пользовательского запроса будет возвращен правильный набор постраничных постов.

    Использование пользовательского объекта запроса для функций разбиения на страницы

    Чтобы функции разбиения на страницы могли выдавать правильный вывод, т. е. ссылки на предыдущую / следующую страницу, относящиеся к пользовательскому запросу, WordPress необходимо принудительно распознать пользовательский запрос. Это требует некоторого «взлома»: замена основного объекта $ 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- & gt; max_num_pages :

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

    Все вместе

    Ниже приведена базовая конструкция пользовательского цикла запроса с правильно функционирующими функциями нумерации страниц:

    // Определить пользовательские параметры запроса
    $custom_query_args = array( /* Параметры */ );
    
    // Получить текущую страницу и добавить к массиву пользовательских параметров запроса
    $custom_query_args['paged'] = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
    
    // Создание пользовательского запроса
    $custom_query = new WP_Query( $custom_query_args );
    
    // Исправление нумерации страниц
    $temp_query = $wp_query;
    $wp_query   = NULL;
    $wp_query   = $custom_query;
    
    // Вывод пользовательского цикла запроса
    if ( $custom_query->have_posts() ) :
        while ( $custom_query->have_posts() ) :
            $custom_query->the_post();
            // Циклический выход
        endwhile;
    endif;
    
    wp_reset_postdata();
    
    // Пользовательский цикл запроса разбиения на страницы 
    previous_posts_link( 'Older Posts' );
    next_posts_link( 'Newer Posts', $custom_query->max_num_pages );
    
    // Сбросить основной объект запроса
    $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() , вы заставляете WordPress заменить основной объект запроса. (На самом деле WordPress делает второй запрос и перезаписывает $wp_query .) Однако проблема в том, что он выполняет эту замену слишком поздно, чтобы обновить нумерацию страниц.

    Решение состоит в том, чтобы отфильтровать основной запрос перед извлечением сообщений , с помощью ловушки pre_get_posts .

    Вместо добавления этого в файл шаблона категории ( category.php ):

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

    Добавьте следующий код в functions.php:

    function wpse120407_pre_get_posts( $query ) {
      
        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 ) {
      
        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' );
    

    Таким образом, WordPress будет использовать уже измененный объект $ wp_query при определении нумерации страниц без необходимости изменения шаблона.

  3. webvitaly

    Я использую этот код для пользовательского цикла с нумерацией страниц:

    <?php
    if ( get_query_var('paged') ) {
        $paged = get_query_var('paged');
    } elseif ( get_query_var('page') ) { // 'page' вместо 'paged' на статической главной странице
        $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. mrwweb

      Еще один хороший учебник с вариантом этого ответа: callmenick.com/post/custom-wordpress-loop-with-pagination

  4. Tom Auger

    Рассмотрим ситуацию, когда вы используете глобальный шаблон страницы, прикрепленный к странице для некоторого «вводного текста», и за ним следует подзапрос, который вы хотите поместить на страницу.

    Используя paginate_links (), как вы упомянули выше, с большей частью значений по умолчанию (и при условии, что у вас включены ЧПУ), ваши ссылки на страницы будут по умолчанию будут иметь значение mysite.ca/page-slug/page/# Но будет ошибка 404, так как WordPress не знает об этой конкретной структуре URL и на самом деле будет искать дочернюю страницу «page», которая является дочерней для «page-slug».

    Хитрость заключается в том, чтобы вставить правило перезаписи, которое применяется только к тому конкретному слагу страницы «страница псевдоархива», который принимает структуру /page/#/ и переписывает его в строку запроса, которую может понять WordPress, а именно: 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" );
    

    Как всегда, при изменении правил перезаписи не забудьте очистить ваши постоянные ссылки , зайдя в Настройки>Постоянные ссылки в административной части.

    Если у вас есть несколько страниц, которые будут вести себя таким образом (например, при работе с несколькими пользовательскими типами записей), вы можете не создавать новое правило перезаписи для каждого блока страниц. Мы можем написать более общее регулярное выражение, которое будет работать для любого идентифицированного фрагмента страницы.

    Например:

    function wpse_120407_pseudo_archive_rewrite(){
        // добавление слагов страниц, которые используют глобальный шаблон для имитации того, что они являются «архивной» страницей
        $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' );
    

    Недостатки / Предостережения

    Одним из недостатков этого подхода является жесткое кодирование Page. Если администратор когда-либо изменит слаг этой страницы псевдоархива, правило перезаписи больше не будет совпадать, и вы получите ошибку 404.

    Я не уверен, что могу придумать обходной путь для этого метода, но было бы неплохо, если бы это был глобальный шаблон страницы, который каким-то образом вызывал правило перезаписи.

Добавить ответ

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: