我认为这里最干净的方法就是运行一个自定义查询,获取ID,然后使用post__not_in
. 您还可以在函数中运行查询,然后在您的特色部分和中调用该函数pre_get_posts
. 还有另一种方法,使用全局函数将ID从自定义查询传递到主查询,但您应该never 走这条路。你必须不惜一切代价避免创建globals,它们是邪恶的
请注意全局变量和变量,避免使用$posts
, $post
和$wp_query
作为变量并向其分配自定义值。这三个是Wordpress使用的全局变量,其中包含主查询对象和主查询中的post对象。将任何其他自定义值赋给它会打断这些全局值。您唯一应该使用这些全局变量的时间是get_posts()
具有setup_postdata()
. setup_postdata()
仅适用于$post
全局,任何其他全局名称都不起作用。这就是为什么你应该使用wp_reset_postdata()
在您的foreach
使用时循环setup_postdata()
重置$post
全局到主查询中的最后一篇文章
示例:
$q = get_posts( \'posts_per_page=1\' );
if ( $q ) {
foreach ( $q as $post ) {
setup_postdata( $post );
// Run loop as normal with template tags
}
wp_reset_postdata();
}
现在,让我们看看眼前的真正问题。我们在这里要做的是创建一个函数,我们可以在我们的特色部分中使用它
pre_get_posts
.
(以下代码未经测试,需要PHP 5.4以上版本。请根据需要随意修改)
function get_featured_custom_post( $main_query = false )
{
/*
* For the purpose of performance, I have created a variable called $main_query with a value of false
* When we run this function in pre_get_posts, we just need the post id, nothing more. For this, our argumaents will change
* The default is meant to return the complete post object, that is for the featured section
*/
if ( $main_query == true ) {
$fields = [\'fields\' => \'ids\'];
} else {
$fields = [\'fields\' => \'all\'];
}
// Build our query arguments
$defaults = [
\'numberposts\' => 1,
\'post_type\' => \'post\',
\'meta_key\' => \'featured_post\',
\'meta_value\' => true
];
$args = wp_parse_args( $defaults, $fields );
$q = get_posts( $args );
return $q;
}
我们功能的价值
get_featured_custom_post
将保存一个具有特征帖子id的数组或完整的帖子对象。现在,让我们使用它
在中pre_get_posts
add_action( \'pre_get_posts\', function ( $q )
{
if ( $q->is_home() // Targets the home page only
&& $q->is_main_query() // Targts the main query only
) {
// Get the post to exclude, remeber, we need id only, so set $main_query to true
$exclude = get_featured_custom_post( true );
if ( $exclude ) // Only set post__not_in if we have a post to exclude, otherwise the result might be unexpected
$q->set( \'post__not_in\', (array) $exclude );
}
});
在我们的特色部分中,我们可以使用以下功能
$q = get_featured_custom_post(); // We need the complete post object, so leave $main_query at default which is false
if ( $q ) {
foreach ( $q as $post ) {
setup_postdata( $post );
// Run loop as normal with template tags
}
wp_reset_postdata();
}