使用自定义查询时,分页不适用于自定义分类-404错误

时间:2020-07-06 作者:pixelngrain

我在使用自定义查询为自定义分类法存档进行分页时遇到问题。分类法归档上的分页以404页结束。

我必须在许多区域上多次运行查询,因此我为此创建了一个方法。

查询方法

/**
 * @param bool  $post_type
 * @param bool  $posts_per_page
 * @param bool  $paged
 * @param array $extra_args
 *
 * @return \\WP_Query
 */
public function module_query( $post_type = FALSE, $posts_per_page = FALSE, $paged = FALSE, array $extra_args = [] ) {
    // basic arguments
    $args = [
        \'post_type\'      => $post_type ? $post_type : self::get_module_cpt(),
        \'posts_per_page\' => $posts_per_page ? $posts_per_page : - 1,
        \'orderby\'        => \'title\',
        \'order\'          => \'ASC\',
    ];

    // set paged
    if ( $paged ) {
        $args[ \'paged\' ] = $paged;
    }

    $args = wp_parse_args( $extra_args, $args );

    // init meta query var
    $meta_query   = [];
    $meta_query[] = [
        \'relation\' => \'AND\',
        [
            \'key\'     => \'permit_roles\',
            \'compare\' => \'NOT EXISTS\',
        ],
        [
            \'key\'     => \'permit_users\',
            \'compare\' => \'NOT EXISTS\',
        ],
    ];
    $meta_query[] = [
        \'relation\' => \'AND\',
        [
            \'key\'     => \'permit_roles\',
            \'value\'   => \'\',
            \'compare\' => \'=\',
        ],
        [
            \'key\'     => \'permit_users\',
            \'value\'   => \'\',
            \'compare\' => \'=\',
        ],
    ];

    // init permit roles var
    $permit_roles = [];
    $r            = 0;

    // loop through each roles and prepare array for meta query
    foreach ( $this->get_current_user_roles() as $current_user_role ) {
        $permit_roles[ $r ][ \'key\' ]     = \'permit_roles\';
        $permit_roles[ $r ][ \'value\' ]   = sprintf( \':"%s";\', $current_user_role );
        $permit_roles[ $r ][ \'compare\' ] = \'LIKE\';

        $r ++;
    }

    $meta_query[] = [
        \'relation\' => \'OR\',
        $permit_roles,
        [
            \'key\'     => \'permit_users\',
            \'value\'   => sprintf( \':"%s";\', get_current_user_id() ),
            \'compare\' => \'LIKE\',
        ],
    ];

    // add meta query relation if more than one query
    if ( count( $meta_query ) > 1 ) {
        $meta_query[ \'relation\' ] = \'OR\';
    }

    // add meta query only for non admin users
    if ( ! current_user_can( \'administrator\' ) ) {
        $args[ \'meta_query\' ] = $meta_query;
    }

    // return the query object
    return new WP_Query( $args );
}
分类法。php查询
$paged = ( get_query_var( \'paged\' ) ) ? get_query_var( \'paged\' ) : 1;

$the_query = $cp->module_query(
    $cp::get_resource_cpt(), cp_get_addons_per_page(), $paged,
    [
        \'orderby\'   => \'publish_date\',
        \'tax_query\' => [
            \'taxonomy\' => $term->taxonomy,
            \'field\'    => \'slug\',
            \'terms\'    => [ $term->slug ],
            \'operator\' => \'IN\',
        ],
    ]
);

...
// while loop
...

// pagination
$cp->bootstrap_pagination( $the_query );

// reset query
wp_reset_postdata();
分页功能在使用acustom循环的自定义Post time页面上分页工作正常。

function bootstrap_pagination( \\WP_Query $wp_query = NULL, $echo = TRUE ) {

    if ( NULL === $wp_query ) {
        global $wp_query;
    }

    $pages = paginate_links( [
            \'base\'         => str_replace( 999999999, \'%#%\', esc_url( get_pagenum_link( 999999999 ) ) ),
            \'format\'       => \'?paged=%#%\',
            \'current\'      => max( 1, get_query_var( \'paged\' ) ),
            \'total\'        => $wp_query->max_num_pages,
            \'type\'         => \'array\',
            \'show_all\'     => FALSE,
            \'end_size\'     => 3,
            \'mid_size\'     => 1,
            \'prev_next\'    => TRUE,
            \'prev_text\'    => __( \'« Prev\' ),
            \'next_text\'    => __( \'Next »\' ),
            \'add_args\'     => FALSE,
            \'add_fragment\' => \'\',
        ]
    );

    if ( is_array( $pages ) ) {

        $pagination = \'<div class="row"><div class="col mt-5"><div class="pagination d-flex justify-content-center"><ul class="pagination pagination-sm">\';

        foreach ( $pages as $page ) {
            $pagination .= \'<li class="page-item\' . ( strpos( $page, \'current\' ) !== FALSE ? \' active\' : \'\' ) . \'"> \' . str_replace( \'page-numbers\', \'page-link\', $page ) . \'</li>\';
        }

        $pagination .= \'</ul></div></div></div><!-- end pagination -->\';

        if ( $echo ) {
            echo $pagination;
        } else {
            return $pagination;
        }
    }

    return NULL;
}

2 个回复
最合适的回答,由SO网友:Sally CJ 整理而成

简而言之,您的代码很好,但自定义查询的分页和主查询的分页不能使用相同的分页paged URL查询字符串(WordPress从中读取paged 中使用的查询参数WP_Query 请求)。

为什么会出现404错误

例如,分页/分页类别请求可以具有以下URL之一:

完整漂亮的URL:
https://example.com/category/uncategorized/page/2/

重定向到上述URL的半漂亮URL:
https://example.com/category/uncategorized/?paged=2

  • ”;丑陋的URL“;(例如,未启用永久链接时)
    https://example.com/?cat=1&paged=2

    如您所见,URL使用的是查询字符串paged 你可以使用get_query_var( \'paged\' ). (请注意,在第一个URL中page/2 相当于paged=2)

    因为类别/分类归档是non-单一请求(就像搜索结果页面一样)paged 值将用于主查询的请求,即用于查询请求的存档的SQL命令,当然,除非主查询未启用分页。

    因此paged 值必须有效,即不得超过该特定请求(主查询)的最大页数。如果超过最大值,则会得到404 错误,因为通过主查询找不到更多帖子。就像一本10页(包括封面)的书;逻辑上没有第11页,对吗?

    因此,因为您的自定义查询正在使用paged 查询字符串,那么如果出现错误404,很可能是因为自定义查询的页面比主查询的页面多。

    演示上述内容的示例场景:

    在类别存档页上(例如example.com/category/uncategorized), 分页中显示了3页。这是WordPress在页面加载时首先运行的主查询。

    然后在类别模板中,运行自定义查询,可能是自定义帖子类型。

    然后,您为自定义查询添加了分页,该分页中显示了5个页面。

    如果两个分页使用相同的paged 例如,转到第#4页将导致404 错误,因为主查询(类别)最多只有3页结果。

    如何修复错误(Note: 这些列在无特定顺序中)

    正如我在评论中所说,您可以使用自定义URL查询字符串,如page_num, pg, 等,以及paged.

    所以paged 将始终仅用于主查询,而page_numpg 将与自定义查询一起使用。

    改为使用AJAX对自定义查询分页,但AJAX不在本答案的范围内。(或者由您自己寻找并实施解决方案。)

    使用静态页面(发布page 类型),例如atexample.com/my-tax-archive, 并在页面模板中运行自定义查询。

    对于单数请求,WordPress不使用paged 在请求SQL中paged 值可以是任意数字(2、20、200、2000等)。

    但是有一个窍门paged 适用于主查询和自定义查询。。在存档页上functions.php 文件:

    add_action( \'pre_get_posts\', function ( $query ) {
        if ( is_admin() || ! $query->is_main_query() ||
            ! is_tax( \'your_tax\' ) ) {
            return;
        }
    
        if ( ! empty( $_GET[\'pgs\'] ) &&
            ( $paged = max( 1, $query->get( \'paged\' ) ) ) &&
            // Runs only if the current page number exceeds the main query\'s max pages.
            $paged > $_GET[\'pgs\']
        ) {
            $query->set( \'pg\', $paged );          // for the custom query\'s pagination
            $query->set( \'paged\', $_GET[\'pgs\'] ); // for the main query\'s pagination
    
            // Prevent WordPress from redirecting to page/<max pages>.
            remove_action( \'template_redirect\', \'redirect_canonical\' );
        } else {
            $query->set( \'pg\', $query->get( \'paged\' ) );
        }
    } );
    
    bootstrap_pagination() 函数,应用四个([1][4]) 更改如下:

    // [1] Add the $use_alt
    function bootstrap_pagination( \\WP_Query $wp_query = NULL, $echo = TRUE, $use_alt = null ) {
    
        ...
    
        // [2] Add these:
        $add_args = [];
        if ( $use_alt ) {
            $add_args[\'pgs\'] = $GLOBALS[\'wp_query\']->max_num_pages;
        }
    
        $pages = paginate_links( [
                ...
                // [3] Use this instead.
                \'current\'      => max( 1, get_query_var( $use_alt ? \'pg\' : \'paged\' ) ),
                ...
                // [4] Use the $add_args
                \'add_args\'     => $add_args,
                ...
            ]
        );
    
        ...
    }
    
    taxonomy.php 模板:

    // Define the $paged like so:
    $paged = max( 1, get_query_var( \'pg\' ) );
    
    // ... your code here.
    
    // Then call bootstrap_pagination() like so:
    bootstrap_pagination( $the_query, true, true );
    
  • 尝试(&O);测试正常,但正如您在上面所看到的,一旦达到主查询的最大页数,接下来的页面将设置paged 最大页数值。因此,如何避免这种情况,取决于你自己。”;看起来很糟糕/怪异/随便什么”;以及处理诸如性能之类的问题(如果自定义查询比主查询多出20个页面,那么人们会看到主查询的最后一个页面20次……如果他们全部查看)。

    SO网友:Divyesh Sapariya

    如果您面临同样的问题,请转到“设置”中的“阅读选项”页面,检查“设置”中设置了多少数字;博客页面最多显示“;字段值。“如果”;博客页面最多显示“;设置的值大于与自定义存档页面或每页post参数的默认页面查询字符串相比的值,因此您需要更改后端";博客页面最多显示“;字段值与每页自定义查询的post值匹配。

    例如:
    ;博客页面最多显示“;字段值为12,我的自定义查询为

    $args = array(
        \'post_type\' => \'post\',
        \'posts_per_page\' => 10,
        \'tax_query\' => array(
            \'relation\' => \'OR\',
            array(
                \'taxonomy\' => \'category\',
                \'field\' => \'id\',
                \'include_children\' => true,
                \'terms\' => array(get_queried_object_id())
            )
        ),
        \'paged\' => $paged
    );
    $wp_query = new WP_Query($args);
    
    在上面的查询中,您会看到posts\\u per\\u page参数值为10,但我们在后端设置了12,因此它将导致分页页面出现问题,因为它将考虑每页12篇文章,所以请将12更改为10,分页将正常工作,在我的情况下,它工作正常。