我如何创建一个类别登录页面,后跟多个帖子页面?

时间:2015-10-20 作者:willcwelch

我正在尝试在我的主题中创建一个类别模板,如果用户位于存档的第一页,该模板将显示静态内容,然后在以下页面上显示类别中的帖子。我基本上是想复制Wired上的分类行为。com何处http://www.wired.com/category/design 是一个登录页,而/category/design/page/1显示的是一个反向按时间顺序排列的帖子列表,就像你在分类档案中所期望的那样。

这里的关键是,我没有在第一页显示类别存档中的任何帖子,所以我需要下一页从第一篇帖子开始。我第一次尝试使用offset and manual pagination 如果“分页”查询变量为2,则将查询的偏移量设置为0。但是偏移量设置为零时会被忽略,所以我只能将偏移量设置为1,然后从类别中的第二篇文章开始。

这就是我添加到函数中的内容。php:

add_action(\'pre_get_posts\', \'category_query_offset\', 1 );
function category_query_offset(&$query) {
  // Before anything else, make sure this is the right query
  if (!$query->is_category(\'news\')) {
    return;
  }

  // Next, determine how many posts per page
  $ppp = get_option(\'posts_per_page\');

  //Next, detect and handle pagination
  if ($query->is_paged) {
    // Manually determine page query offset
    $page_offset = (($query->query_vars[\'paged\']-1) * $ppp) - $ppp;
    // Apply adjust page offset
    $query->set(\'offset\', $page_offset );
  }
}
更好的做法是使用默认分页,使帖子从第1页开始,但为静态内容插入第0页。假设,如果“paged”为0,则显示静态内容,如果“paged”为1,则显示文章的第一页,这似乎是可能的。问题是“paged”永远不是1,因为Wordpress在用户请求第一页时将“paged”设置为零。这意味着/category/news/page/1和/category/news的“paged”都是0。

是否有办法检查用户是否请求了/category/news/page/1而不是/category/news?否则,是否有办法从第2页开始显示类别中的所有帖子?

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

这是一个非常有趣的问题(我对这个问题投了赞成票,特别是针对你的方法和研究)。此处的大曲线球是查询的第一页:

无法将查询设置为返回0 第一页上的帖子

通过将每个页面的页面内容上移一页,您将失去最后一页,因为查询仍然只有相同数量的帖子,因此$max_num_pages 财产仍将保持不变

我们需要以某种方式“欺骗”WP_Query 类以正确返回偏移量为一页的帖子,并获得正确的页数,以避免查询中的最后一页丢失

让我们看看下面的想法,并尝试将所有内容都放在代码中。然而,在此之前,我想提出几点意见

重要提示:所有内容都未经测试,因此可能有问题。确保在启用调试的情况下在本地测试此功能

该代码至少需要PHP 5.3,低于5.3的任何版本都会导致致命错误。注意,如果您仍在使用PHP 5.5以下的任何版本,那么您早就应该升级了

根据您的具体需要,在您认为合适的情况下修改和滥用代码

灯泡理念:

WHAT WE WILL NEED

为了使一切顺利进行,我们需要以下方面:

当前正在查看的页码

posts_per_page 阅读设置中的选项集

自定义offset

修改$found_posts 属性来更正$max_num_pages 所有物

分页是WP_Query 下面是非常简单的几行代码

if ( empty($q[\'nopaging\']) && !$this->is_singular ) {
    $page = absint($q[\'paged\']);
    if ( !$page )
        $page = 1;
    // If \'offset\' is provided, it takes precedence over \'paged\'.
    if ( isset( $q[\'offset\'] ) && is_numeric( $q[\'offset\'] ) ) {
        $q[\'offset\'] = absint( $q[\'offset\'] );
        $pgstrt = $q[\'offset\'] . \', \';
    } else {
        $pgstrt = absint( ( $page - 1 ) * $q[\'posts_per_page\'] ) . \', \';
    }
    $limits = \'LIMIT \' . $pgstrt . $q[\'posts_per_page\'];
}
基本情况是,一旦明确设置了偏移量paged 参数被忽略。SQL的第一个参数LIMIT 子句将根据偏移量重新计算,并将是生成的SQL查询中要跳过的帖子数。

从你的问题来看,显然是在设置offset0, 偏移量查询失败,这很奇怪,因为下面的检查应该返回true

if ( isset( $q[\'offset\'] ) && is_numeric( $q[\'offset\'] ) )
0是有效数字,应返回true。如果在安装中没有这样做,则应调试该问题

为了回到手头的问题,我们将使用相同的逻辑来计算和设置偏移量,以获得第2页的第1篇文章,并从那里对查询进行分页。对于第一页,我们不会更改任何内容,因此假定在第1页上的帖子仍将正常在第1页上,我们只需要稍后“隐藏”它们,以便不在第1页上显示它们

add_action( \'pre_get_posts\', function ( $q )
{
    if (    !is_admin() // Only target the front end, VERY VERY IMPORTANT
         && $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT
         && $q->is_cateory( \'news\' ) // Only target the news category
    ) {
        $current_page = $q->get( \'paged\' ); // Get the current page number
        // We will only need to run this from page 2 onwards
        if ( $current_page != 0 ) { // You can also use if ( is_paged() ) {
            // Get the amount of posts per page
            $posts_per_page = get_option( \'posts_per_page\' );
            // Recalculate our offset
            $offset = ( ( $current_page - 1) * $posts_per_page ) - $posts_per_page; // This should work on page 2 where it returns 0

            // Set our offset
            $q->set( \'offset\', $offset );
        }
    }
});
你应该在第2页的第1页看到相同的帖子。如前所述,如果不发生这种情况is_numeric( 0 ) 正在返回false(,不应该返回),或者您有另一个pre_get_posts 同时尝试设置偏移或正在使用的操作posts_* 子句筛选器(更具体地说,是post_limits 过滤器)。这将是您需要自己调试的东西。

下一个问题是更正分页,因为正如我前面所说的,您将缺一页。为此,我们需要增加get_option( \'posts_per_page\' ) 在查询中找到的帖子数量,因为我们用该数量抵消了查询。通过这样做,我们有效地增加了1$max_num_pages 所有物

add_action( \'found_posts\', function ( $found_posts, $q )
{
    if (    !is_admin() // Only target the front end, VERY VERY IMPORTANT
         && $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT
         && $q->is_cateory( \'news\' ) // Only target the news category
    ) {
        $found_posts = $found_posts + get_option( \'posts_per_page\');
    }
}, 10, 2 );
这应该对所有内容进行排序,除了第一页。

现在所有人都在一起(,特别是@ialocin-Yellow Submarine

这些都应该functions.php

add_action( \'pre_get_posts\', function ( $q )
{
    if (    !is_admin() // Only target the front end, VERY VERY IMPORTANT
         && $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT
         && $q->is_cateory( \'news\' ) // Only target the news category
    ) {
        $current_page = $q->get( \'paged\' ); // Get the current page number
        // We will only need to run this from page 2 onwards
        if ( $current_page != 0 ) { // You can also use if ( is_paged() ) {
            // Get the amount of posts per page
            $posts_per_page = get_option( \'posts_per_page\' );
            // Recalculate our offset
            $offset = ( ( $current_page - 1) * $posts_per_page ) - $posts_per_page; // This should work on page 2 where it returns 0

            // Set our offset
            $q->set( \'offset\', $offset );
        }
    }
});

add_filter( \'found_posts\', function ( $found_posts, $q )
{
    if (    !is_admin() // Only target the front end, VERY VERY IMPORTANT
         && $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT
         && $q->is_cateory( \'news\' ) // Only target the news category
    ) {
        $found_posts = $found_posts + get_option( \'posts_per_page\');
    }
    return $found_posts;
}, 10, 2 );
首页选项这里有几个选项:

OPTION 1

我很可能会选择这个选项。您想在这里做的是创建category-news.php如果尚未执行此操作)。这将是在news 查看类别。此模板将非常简单

实例

<?php
get_header()

if ( !is_paged() ) { // This is the first page
    get_template_part( \'news\', \'special\' );
} else { // This is not the first page
    get_template_part( \'news\', \'loop\' );
}

get_sidebar();
get_footer();
如您所见,我包含了两个模板部分,news-special.phpnews-loop.php. 现在,这两个自定义模板的基础是:

  • news-special.php -> 此模板部分将是您希望在第一页上显示的任何内容。在此处添加所有自定义静态信息。请注意不要在此模板中调用循环,因为这样会显示第一页的帖子。

  • news-loop.php -> 这是我们将调用循环的模板。此部分将如下所示:

    global $wp_query;
    while ( have_posts() ) {
    the_post();
    
        // Your template tags and markup
    
    }
    
    选项2用静态内容创建一个单独的模板,只需使用category_template 当我们查看news 类别此外,请确保不要调用此模板中的默认循环。此外,请确保此处的命名约定不会与模板层次结构中的模板名称冲突

    我希望这是有用的。请随时发表评论,表达关切

    编辑由于OP,在WP_Query 类,检查trac ticket #34060. 我发布的代码来自Wordpress v4。4,该错误在此版本中已修复。

    我回到了v4的源代码。3,bug在哪里,我可以确认0 设置为值时忽略offset 因为代码只是检查offset 参数为empty. 0 在PHP中被视为空。我不确定这种行为(bug)是否只在v4中找到。3或在所有以前的版本中(根据票据,此错误在v4.3中),但此错误有一个补丁,您可以在trac票据中查看。正如我所说,这个bug肯定在v4中得到了修复。4.

SO网友:Khaled Sadek

Update:

add_action(\'pre_get_posts\', \'category_query_offset\', 1 );
function category_query_offset($query) {
 // Before anything else, make sure this is the right query
 if (!$query->is_category(\'news\')) {
    return;
 }

 // Next, determine paged
 $ppp = get_option(\'paged\');
}
// Next, handle paged
if($ppp > 1){
    $query->set(\'paged\', $ppp-1);
}
试试这样的东西

$paged = ( get_query_var(\'paged\') ) ? get_query_var(\'paged\')-1 : 1;
$args = array (
    \'paged\' => $paged,
);

相关推荐

Ajax Filtering Pagination

我知道这是一个常见的问题,但我找不到解决办法。我在用户点击复选框时进行了ajax过滤。在用户单击分页之前,一切都正常。当然,我们现在使用的是管理ajax。php页面和分页链接不工作。这是代码。HTML复选框:<input type=\"checkbox\" id=\"telegram_chk\" checked> <input type=\"checkbox\" id=\"twitter_chk\" checked> <input type=\"checkbo