WP_Query Pagination на single-custom.php

16

Что я хочу сделать:

Настройка WP_Queryпагинации в одном файле шаблона custom-post-type.php

Что я наделал

1) Создан тип поста под названием «авторы». Каждый пост в этом типе поста является отдельным автором.

2) Стандартные страницы экрана редактирования постов содержат выпадающий список, в котором перечислены все посты (авторы) от автора тип поста.

3) Создал шаблон single -hors.php, который запрашивает все сообщения с метаданными автора из выпадающего списка, поэтому в результате получается список сообщений, которым назначен один и тот же автор (вроде архива):

<?php

// set the "paged" parameter (use 'page' if the query is on a static front page)
global $paged;

/*We need this here to add and maintain Pagination if Template is assigned to Front Page*/
if ( get_query_var( 'paged' ) ) {
    $paged = get_query_var('paged');
} elseif ( get_query_var( 'page' ) ) {
    $paged = get_query_var( 'page' );
} else {
    $paged = 1;
}

$args = array(
    'posts_per_page'    =>  10,
    'meta_key'          => 'author_select',
    'meta_value'        => $author_id,
    'paged'             => $paged,
);

$temp = $wp_query;
$wp_query = NULL;

$wp_query = new WP_Query($args);

?>

<?php if( $wp_query->have_posts() ) : ?>    
    <?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>
    <?php // Successfully outputs the results of the above query, so I've omitted the code from this example. ?>

    <?php endwhile; ?>

<div class="single_navigation"> 
    <?php if( get_adjacent_post( false, '', true ) ) { ?>
        <span class="prev"><?php previous_post_link( '&lt; %link' ) ?></span>
    <?php } ?>

    <?php if( get_adjacent_post( false, '', false ) ) { ?>
        <span class="next"><?php next_post_link( '%link &gt;' ) ?></span>
    <?php } ?>
    </div><!--/single navigation-->
<?php endif; ?>

<?php
    $wp_query = null;
    $wp_query = $temp;
    wp_reset_query();
?>

На чем я застрял

Ссылки на страницы не отображаются. Я провел некоторое исследование и обнаружил, что они используют $wp_queryпеременную, однако, когда я изменил свою переменную запроса на $wp_query, появились ссылки, но при нажатии ничего не произошло.

Есть идеи, где я иду не так?

Редактировать:

Чтобы ответить на некоторые ваши вопросы, мой запрос успешно выводит сообщения, которые я запрашиваю, $ author_id уже имеет значение, которое я не включил в этот фрагмент кода. Точно так же я пропустил фактический вывод содержимого в цикле while, потому что эта часть не является проблемой. Проблема в том, что мне нужно разбить содержимое уже существующего на этот пост.

Цель этой функциональности состояла в том, чтобы позволить постам иметь собственных авторов (вне встроенной системы Users), и целью этого шаблона является вывод всех постов для данного автора (который уже работает).

Шейн
источник
3
Возвышение за хорошо отформатированный вопрос, хотя вы не описали, почему вы это делаете, это связанные посты от текущего автора?
Том Дж. Новелл
1
Я действительно согласен с @TomJNowell. +1
Питер Гусен
2
Не имеет отношения, но не нужно повторятьthe_title()
Питер Гусен
2
Является ли 'meta_value' => $author_idзаполняется из выпадающего списка упоминается? И при выборе каждого автора через выпадающий список правильно отображаются первые десять сообщений?
Стивен С.
1
Вы убедились, что $author_query->have_posts()возвращается trueи что на $author_queryсамом деле содержит какие-либо сообщения?
Кайзер

Ответы:

17

У вас 2 проблемы.

Первая проблема

Линия

$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;

потерпит неудачу, потому что в единственном представлении поста, когда URL содержит '/page/XX/', переменная WordPress устанавливает, 'page'а не 'paged'.

Вы можете подумать о том, чтобы использовать 'page'вместо 'paged', но это тоже не сработает, потому что, как только 'page'переменная предназначена для использования в многостраничной отдельной публикации (с использованием разделения страниц <!--nextpage-->), и когда публикация не многостраничная, WordPress перенаправит запрос. на URL без '/page/XX/'.

Это то, что происходит, когда вы называете свою переменную запроса $wp_query.

Решение состоит в том, чтобы предотвратить это перенаправление путем удаления ответственной за него функции, которая 'redirect_canonical'подключается к 'template_redirect':

Итак, в вашем functions.phpдобавлении:

add_action( 'template_redirect', function() {
    if ( is_singular( 'authors' ) ) {
        global $wp_query;
        $page = ( int ) $wp_query->get( 'page' );
        if ( $page > 1 ) {
            // convert 'page' to 'paged'
            $wp_query->set( 'page', 1 );
            $wp_query->set( 'paged', $page );
        }
        // prevent redirect
        remove_action( 'template_redirect', 'redirect_canonical' );
    }
}, 0 ); // on priority 0 to remove 'redirect_canonical' added with priority 10

Теперь WordPress больше не будет перенаправлять и правильно установит 'paged'запрос var.

Вторая проблема

next_posts_link()и previous_posts_link()обе проверки if ( ! is_single() )для отображения нумерации страниц.

Теперь is_single()верно в вашем случае, потому что вы находитесь в одном посте типа «автор», поэтому эти функции не могут работать так, как вы ожидаете.

У вас есть 3 возможности:

  1. Используйте query_postsдля переопределения основного запроса (на самом деле не рекомендуется)
  2. Используйте пользовательский шаблон страницы вместо пользовательского типа публикации, потому что is_single()это ложно для страниц, и ваш код будет работать там.
  3. Напишите свою собственную функцию нумерации страниц и используйте это

Это код для решения № 3:

function my_pagination_link( $label = NULL, $dir = 'next', WP_Query $query = NULL ) {
    if ( is_null( $query ) ) {
        $query = $GLOBALS['wp_query'];
    }
    $max_page = ( int ) $query->max_num_pages;
    // only one page for the query, do nothing
    if ( $max_page <= 1 ) {
        return;
    }
    $paged = ( int ) $query->get( 'paged' );
    if ( empty( $paged ) ) {
        $paged = 1;
    }
    $target_page = $dir === 'next' ?  $paged + 1 : $paged - 1;
    // if 1st page requiring previous or last page requiring next, do nothing
    if ( $target_page < 1 || $target_page > $max_page ) {
        return;
    }
    if ( null === $label ) {
        $label = __( 'Next Page &raquo;' );
    }

    $label = preg_replace( '/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $label );
    printf( '<a href="%s">%s</a>', get_pagenum_link( $target_page ), esc_html( $label ) );
}

и используйте это так в single-authors.php:

my_pagination_link( 'Older Entries', 'next', $author_query );
my_pagination_link( 'Newer Entries', 'prev', $author_query );
gmazzap
источник
Очень подробный ответ, спасибо! Это работает для английской стороны сайта, но на французской стороне нумерация ссылок на страницы ничего не делает, они только обновляют страницу. Я использую WPML.
Шейн
1
@Shane так кажется, что WPML запускает какой-то фильтр, который мешает работе кода. Но это такой большой плагин, и поэтому я не могу копать тысячи строк кода, чтобы понять, где конфликт. Попробуйте спросить поддержку WPML.
gmazzap
@Shane Форумы поддержки WPML - и если вышеописанное работает для (что я предполагаю), то, пожалуйста, пометьте его как решение. Конфликт WPML вне темы / выходит за рамки этого сайта в любом случае.
кайзер
Фантастический ответ, в основном потому, что он помог мне решить проблему с нумерацией страниц. Я выполнял аналогичную задачу и создал второй WP_Query для зацикливания. Я позвонил, the_posts_paginationно мне пришлось взять копию оригинального wp_query, как указано в этом вопросе: wordpress.stackexchange.com/questions/216821/…
Александр Холсгроув
1
Вы правы @HongPong, исправлено, спасибо.
gmazzap
0

Основываясь на другом подобном вопросе WPSE « Разбиение на страницы не работает значения пользовательских полей wp_query », я бы предложил добавить global $paged;в начало вашего файла шаблона:

global $paged;
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
Стивен С.
источник
1
Спасибо за ответ! К сожалению, это не имеет никакого значения. Ссылки на страницы не появляются
Шейн
1
Стивен, почему это должно помочь? Да, это принесет это из глобального контекста, но пока вы ничего не делаете с этим. Если вы хотите переопределить глобальный, то используйте $GLOBALS['paged'] = get_query_var( 'paged' );. Остальное просто используй контент globals.
Кайзер
@ Шейн Хмм, страница шаблона используется в качестве статической главной страницы?
Стивен С.
Нет, он используется только как отдельный шаблон сообщения для пользовательского типа сообщения. Я пытался изменить свой запрос с $author_queryна, $wp_queryи это, казалось, делало нумерацию страниц, но когда я нажимаю на нее, страница обновляется и фактически не переходит на следующую страницу, даже если есть несколько страниц. Я обновил свой ответ, чтобы отразить эти изменения.
Шейн
1
Php.net объяснение не так уж плохо. Я бы посоветовал просто поиграть с globalи $GLOBALS. Немного var_dump(), некоторые функции, и вы в порядке. Чтобы действительно понять это с небольшим количеством попытки / ошибки, вы прибл. нужно полчаса. Это поможет вам лучше понять функции и классы, а также подход ООП в целом. И это явно приблизит вас к пониманию пространств имен :)
kaiser