我的情况有点复杂,我会尽量简洁地解释一下 .
我目前正在使用 query_posts
来修改我网站上自定义页面上的主要查询,据我所知,虽然我已经读到使用query_posts这是一种不好的做法,原因有很多 .
那么,为什么我使用 query_posts
而不是创建一个你可能会问的 WP_Query
对象?
这是因为我使用的是无限滚动插件,无限滚动对WP_query不起作用,但是当你只使用query_posts修改主查询时它完全正常 . 例如,使用无限滚动WP_query(主要关注点)分页不起作用 .
在一个页面上,我正在修改查询以获得最常见的帖子 .
<?php $paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1; ?>
<?php query_posts( array( 'meta_key' => 'wpb_post_views_count', 'orderby' => 'meta_value_num', 'order' => 'DESC' , 'paged' => $paged, ) ); ?>
<?php if (have_posts()) : ?>
<?php while ( have_posts() ) : the_post() ?>
<?php if ( has_post_format( 'video' )) {
get_template_part( 'video-post' );
}elseif ( has_post_format( 'image' )) {
get_template_part( 'image-post' );
} else {
get_template_part( 'standard-post' );
}
?>
<?php endwhile;?>
<?php endif; ?>
所以在经过大量阅读后,我收集到我修改主查询的其他选项是使用 pre_get_posts
,尽管我有点不确定如何解决这个问题 .
以此为例: -
function textdomain_exclude_category( $query ) {
if ( $query->is_home() && $query->is_main_query() ) {
$query->set( 'cat', '-1,-2' );
}
}
add_action( 'pre_get_posts', 'textdomain_exclude_category' );
好吧,这么简单 - 如果它是主页,修改主查询并排除两个类别 .
我感到困惑,无法弄清楚的是: -
-
自定义页面模板的用例场景 . 通过我的
query_posts
修改,我可以在if (have_posts())
之前插入数组,选择我的页面模板,发布它然后我就去了 . 使用pre_get_posts
我无法弄清楚如何说例如$query->most-viewed
等 -
array( 'meta_key' => 'wpb_post_views_count', 'orderby' => 'meta_value_num', 'order' => 'DESC' , 'paged' => $paged, ) );
我怎么做 pre_get_posts
并确保's paginated, ie. works with infinite scroll? In all the examples I'看到 pre_get_posts
没有数组 .
2 回答
如何使用pre_get_posts挂钩通过自定义页面模板显示页面上的帖子列表?
我一直在玩
pre_get_posts
钩子,这是一个想法Step #1:
Ceate一个名为Show with the slug的页面:
Step #2:
创建自定义页面模板:
位于当前主题目录中 .
Step #3:
我们构造以下
pre_get_posts
动作回调:哪里
这也应该给我们分页:
等等
注意事项
我根据@PieterGoosen的建议更新了答案并删除了查询对象部分修改,因为它可以例如打破他的设置上的面包屑 .
还删除了
pre_get_posts
钩子内的is_page()
检查,因为在某些情况下它可能仍会出现一些不规则现象 . 原因是查询对象并不总是可用 . 这正在研究中,参见例如#27015 . 如果我们想使用is_page()
或is_front_page()
,则有workarounds possible .我构建了下表,只是为了更好地概述主
WP_Query
对象的一些属性和查询变量,对于给定的slug:是interesting to note,
WP_Query
中的分页取决于nopaging
未设置且当前页面不是单数(来自4.4 source):我们可以看到生成的SQL查询的
LIMIT
部分在条件检查范围内 . 这解释了为什么我们修改上面的is_singular
属性 .我们可以使用其他过滤器/钩子,但是在这里我们使用OP提到的
pre_get_posts
.希望这有帮助 .
从@birgire回答的灵感,我提出了以下想法 . (注:This is a copy of my answer from this answer over at WPSE)
我在这里尝试做的是宁愿使用后注入而不是完全改变主要查询并且遇到所有上述问题,比如直接改变全局,全局值问题和重新分配页面模板 .
通过使用后期注入,我能够保持完整的帖子完整性,因此
$wp_the_query->post
,$wp_query->post
,$posts
和$post
在整个模板中保持不变,它们都只保存当前页面对象,就像真实页面的情况一样 . 这样,像breadcrumbs这样的函数仍然认为当前页面是真正的页面而不是某种存档我不得不稍微改变主要查询(通过过滤器和动作)以调整分页,但我们将会这样做 .
POST INJECTION QUERY
为了完成后期注入,我使用自定义查询来返回注入所需的帖子 . 我还使用自定义查询的
$found_pages
属性来调整主查询的属性,以便从主查询中获取分页 . 帖子通过loop_end
动作注入主查询 .为了使自定义查询可以在课外访问和使用,我介绍了几个操作 .
分页挂钩以挂钩分页功能:甲
pregetgostsforgages_before_loop_pagination
pregetgostsforgages_after_loop_pagination
自定义计数器,用于计算循环中的帖子 . 这些操作可用于根据帖子编号更改帖子在循环内的显示方式
pregetgostsforgages_counter_before_template_part
pregetgostsforgages_counter_after_template_part
常规钩子,用于访问查询对象和当前帖子对象
pregetgostsforgages_current_post_and_object
这些钩子为您提供完全不干涉的体验,因为您不需要在页面模板本身中更改任何内容,这从一开始就是我的初衷 . 可以从插件或函数文件中完全更改页面,这使得它非常动态
我还使用
get_template_part()
来加载模板部分,用于显示帖子 . 今天的大多数主题都使用模板部分,这使得它在课堂上非常有用 . 如果您的主题使用content.php
,则只需将content
传递给$templatePart
即可加载content.php
.如果你需要模板部分的后期格式支持,这很简单,你仍然只需将
content
传递给$templatePart
并简单地将$postFormatSupport
设置为true
,并且将为帖子格式为video
的帖子加载模板部分content-video.php
主要问题
通过相应的过滤器和操作对主查询进行了以下更改
为了对主查询进行分页:
注入器查询的
$found_posts
属性值通过found_posts
过滤器传递给主查询对象的值通过
pre_get_posts
将用户传递参数posts_per_page
的值设置为主查询$max_num_pages
是使用$found_posts
和posts_per_page
中的帖子数量计算的 . 因为is_singular
在页面上为true,所以它禁止设置LIMIT
子句 . 简单地将is_singular
设置为false会导致一些问题,因此我决定通过post_limits
过滤器设置LIMIT
子句 . 我将LIMIT
子句的offset
设置为0
以避免在分页页面上显示404这样可以处理分页以及后注射可能引起的任何问题
页面对象
当前页面对象可以通过使用页面上的默认循环显示为帖子,单独并在注入的帖子之上 . 如果您不需要,可以将
$removePageFromLoop
设置为true,这将隐藏页面内容的显示 .在这个阶段,我使用CSS通过
loop_start
和loop_end
动作隐藏页面对象,因为我找不到另一种方法 . 这种方法的缺点是,如果隐藏页面对象,默认情况下,隐藏在主查询中的the_post
动作钩子的任何内容都将被隐藏 .THE CLASS
PreGetPostsForPages
类可以改进,并且应该正确地命名空间虽然您可以简单地将它放在主题的函数文件中,但最好将其放入自定义插件中 .根据需要使用,修改和滥用 . 代码评论很好,所以应该很容易遵循和调整
用法
您现在可以启动课程(也在您的插件或函数文件中),如下所示,以ID为251定位页面,我们将在
post
帖子类型上显示每页2个帖子添加分页和定制风格
正如我所说,在注入器查询中有一些操作,以添加分页或自定义样式 . 在这里,我使用my own pagination function from the linked answer在循环后添加了分页 . 此外,使用内置计数器,我添加了一个div来显示我的帖子在两个列中 .
这是我使用的动作
请注意,分页是由主查询设置的,而不是注入器查询,所以像
the_posts_pagination()
这样的内置函数也应该有效 .这是最终结果
静态前页
一切都按照预期在静态首页上与我的分页功能一起工作,而不必进行任何修改
结论
这似乎是一个非常多的开销,可能是,但专业人士超过了骗局的大时间
BIG PRO'S
您无需以任何方式更改特定页面的页面模板 . 这使得一切都变得动态,并且可以在主题之间轻松转移,而无需修改代码,如果一切都在插件中完成的话 .
最多只需要在主题中创建一个
content.php
模板部分,如果你的主题还没有任何适用于主查询的分页都将在页面上起作用,而不会将任何类型的更改或任何额外的查询传递给函数 .
那里我现在想不到更多的亲,但这些是重要的
我希望这将有助于将来的某些人