问题描述
我正在尝试在我的主题中创建一个类别模板,如果用户位于存档的第一页,则会显示静态内容,然后在以下页面上显示类别中的帖子。我基本上是尝试复制 Wired.com 上的类别行为,其中 http://www.wired.com/category/design 是一个着陆页,而/category /design /page /1 显示了类似于期望在类别归档中的反向按时间顺序排列的列表。
这里的关键是,我没有在第一页上显示类别归档中的任何帖子,所以我需要下一页从第一个帖子开始。如果’paged’ 查询 var 为 2,我首先尝试使用 offset and manual pagination 来设置查询的偏移量为 0 。但是当设置为零时,偏移量被忽略,所以我可以做的最好是将偏移量设置为 1,并从该类别中的第二个职位。
这是我添加到 functions.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’ 为 1,那么’paged’ 为 0,并显示第一页帖子,这样就可以显示静态内容。问题是’paged’ 从不是 1,因为 WordPress 将’paged’ 设置为零,当用户请求第一页。这意味着’paged’ 对于/category /news /page /1 和/category /news 都是 0 。
有没有办法检查用户是否要求/category /news /page /1 而不是/category /news?没有,是否有一种方法来显示从第 2 页开始的类别中的所有帖子?
最佳解决方案
这是一个非常有趣的问题 (我特别为您的方法和研究而升级了) 。这里的大曲线球是查询的第一页:
-
您无法设置查询以返回第一页上的
0
帖子 -
通过将每页的页面内容向上移动一页,您将会丢失最后一页,因为查询仍将只具有相同的帖子数量,因此
$max_num_pages
属性仍然保持不变
我们将需要以某种方式”trick” WP_Query
类返回我们的帖子 corectly 与一个页面的偏移,并且还得到正确的页数,以便不松动查询中的最后一页
让我们来看看下面的想法,并尝试将所有内容都放在代码中。在我们做之前,我想在这里提几点
重要笔记:
-
一切都是未经测试的,所以它可能是错误的。确保在本地进行测试,并打开调试开关
-
该代码至少需要 PHP 5.3,5.3 以下版本会导致致命错误。请注意,如果仍然使用下面的 PHP 5.5 版本,您应该已经很久以前升级了
-
修改和滥用您认为适合您的确切需求的代码
光线:
我们需要什么
为了使一切正常,我们将需要以下内容:
-
正在查看的当前页码
-
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 查询中要跳过的帖子数。
从您的问题,显然是将 offset
设置为 0
时,偏移查询失败,这是奇怪的,因为以下检查应该返回 true
if ( isset( $q['offset'] ) && is_numeric( $q['offset'] ) )
0
是一个有效的数字,应该返回 true 。如果您的安装没有,您应该调试问题
为了回到手头的问题,我们将使用相同的逻辑来计算和设置我们的偏移量,以获得第 2 页的帖子 1,并从中分页查询。对于第一页,我们不会更改任何内容,因此假设在第 1 页上的帖子仍然正常,我们稍后将需要”hide”,以便我们不在第 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 );
第一页选项
这里有几个选项:
选项 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.php
和 news-loop.php
。现在,两个自定义模板的基础是:
-
news-special.php
– > 这个模板部分将是您想要显示在第一页上的任何内容。在这里添加所有您的自定义静态信息。要小心,不要在此模板中调用循环,因为这将显示第一页的帖子。 -
news-loop.php
– > 这是我们调用循环的模板。本节将如下所示:global $wp_query; while ( have_posts() ) { the_post(); // Your template tags and markup }
选项 2
使用静态内容创建一个单独的模板,当我们查看 news
类别的第一页时,只需使用 category_template
筛选器即可使用此模板。另外,请确保不要调用此模板中的默认循环。另外,请确保这里的命名约定不会与模板层次结构中的模板名称相冲突
我希望这是有用的。随心所欲地发表评论
EDIT
感谢 OP,WP_Query
类有一个明确的错误,检查 trac ticket #34060 。我发布的代码来自 Wordpress v4.4,该版本中修复了错误。
我回到 v4.3 的源代码,那里的 bug 是,当我设置为 offset
的值时,我可以确认 0
被忽略,因为代码只是检查 offset
参数是 empty
。 PHP 中的 0
为空。我不知道这个行为 (错误) 是否仅在 v4.3 或所有以前的版本中发现 (根据机票,该错误在 v4.3 中),但是有一个补丁可以检查这个错误在 trac 门票里。就像我说的,这个 bug 在 v4.4 中一定是固定的
参考文献
注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。