query_brands_geo('dealers', 'publish', '1', $taxtype, $geo, $brands);
在我的taxonomy.php模板中调用。此功能运行良好。但是,在阅读了用于查询帖子的Codex之后,它提到了pre_get_posts作为更改默认查询的首选方法。 pre_get_posts比下面的wp_query函数更有效吗?
如果是这样,我将如何构造pre_get_posts并在下面传递变量和查询?
function my_custom_query($posttype, $poststatus, $paidvalue, $taxtype, $geo, $brands) {
global $wp_query;
$wp_query = new WP_Query();
$args = array(
'post_type' => $posttype,
'post_status' => array($poststatus),
'orderby' => 'rand',
'posts_per_page' => 30,
'meta_query' => array(
array(
'key' => 'wpcf-paid',
'value' => array($paidvalue),
'compare' => 'IN',
)
),
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => $taxtype,
'field' => 'slug',
'terms' => $geo
),
array(
'taxonomy' => 'brands',
'field' => 'slug',
'terms' => $brands
)
)
);
return $wp_query->query($args);
}
#1 楼
pre_get_posts
将运行相同的查询,因此两者将花费相同的时间。但是,如果使用pre_get_posts
操作,将保存一个或多个SQL查询。现在,WordPress正在运行默认查询,然后您可以使用此函数运行查询,该函数将替换默认查询的结果(结果是,默认查询没有用)。以下是将$args
移至function custom_pre_get_posts($query, $posttype='dealers', $poststatus='publish', $paidvalue='1', $taxtype='any_default_value', $geo='any_default_value', $brands='any_default_value') {
// filter your request here.
if($query->is_category) {
$args = array(
'post_type' => $posttype,
'post_status' => array($poststatus),
'orderby' => 'rand',
'posts_per_page' => 30,
'meta_query' => array(
array(
'key' => 'wpcf-paid',
'value' => array($paidvalue),
'compare' => 'IN',
)
),
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => $taxtype,
'field' => 'slug',
'terms' => $geo
),
array(
'taxonomy' => 'brands',
'field' => 'slug',
'terms' => $brands
)
)
);
$query->query_vars = $args;
}
}
add_action('pre_get_posts', 'custom_pre_get_posts');
的方法
#2 楼
延迟答案是最受好评的答案,它会打断您的查询,并且在某些主要问题上是不正确的。主要的WP_Query及其过滤器
首先,WordPress内部使用
query_posts()
(不要在主题或插件中使用WP_Query
周围的薄包装)来做WP_Query
。该WP_Query
充当主循环/查询。该查询将运行许多过滤器和操作,直到建立实际的SQL查询字符串为止。其中之一是pre_get_posts
。其他的还有posts_clauses
,posts_where
等,它们也允许您拦截查询字符串的构建过程。深入研究内核内部发生了什么
WordPress运行
wp()
函数(在wp-includes/functions.php
中),该函数调用$wp->main()
($wp
是WP类的对象,该类在wp-includes/class-wp.php
中定义)。这告诉WordPress:使用
WP->parse_request()
将URL解析为查询规范-有关以下内容。使用
$wp_query->parse_query()
设置条件标记使用的所有is_变量。 ($wp_query
是class WP_Query
的对象,该对象在wp-includes/query.php
中定义)。请注意,尽管使用了该函数的名称,在这种情况下WP_Query->parse_query
实际上不会为我们做任何解析,因为这是由WP->parse_request()
预先完成的。将查询规范转换为MySQL数据库查询,然后运行数据库查询以在函数WP_Query-> get_posts()中获取帖子列表。将帖子保存在$ wp_query对象中,以在WordPress循环中使用。
源代码
结论
要修改主查询,则可以使用多种过滤器。只需使用
$query->set( 'some_key', 'some_value' );
在那里更改数据或使用$query->get( 'some_key' );
检索数据来进行条件检查。这将使您不必再进行第二次查询,因为您只需要更改SQL查询。如果必须执行其他查询,请使用
WP_Query
对象。这将向数据库添加另一个查询。示例
由于示例总是使答案更好用,所以您在这里得到了一个非常不错的示例(Brad Touesnard的道具),该示例简单地扩展了核心对象,因此非常可重用(使用其中的一个插件):
class My_Book_Query extends WP_Query
{
function __construct( $args = array() )
{
// Forced/default args
$args = array_merge( $args, array(
'posts_per_page' => -1
) );
add_filter( 'posts_fields', array( $this, 'posts_fields' ) );
parent::__construct( $args );
}
public function posts_fields( $sql )
{
return "{$sql}, {$GLOBALS['wpdb']->terms}.name AS 'book_category'";
}
}
然后您可以运行第二个/其他查询,如下面的示例所示。不要忘记稍后重设查询。
$book_query = new My_Book_Query();
if ( $book_query->have_posts() )
{
while ( $book_query->have_posts() )
{
$book_query->the_post();
# ...do stuff...
} // endwhile;
wp_reset_postdata();
} // endif;
#3 楼
请查看何时使用WP_query(),query_posts()和pre_get_posts的答案。如果您有任何疑问,这是一个很好的资源。
评论
非常感谢你的答复。这是非常有帮助的。一个简单的问题。我将函数放在主题function.php文件中。我从我的taxonomy.php运行此函数custom_pre_get_posts($ query)。在taxonomy.php中,我设置了变量$ posttype,$ post_status,$ geo,$ brands,$ taxtype,并运行了两个循环来更改这些变量。有没有办法将变量从taxonomy.php传递到上述函数中?当我尝试custom_pre_get_posts($ query,'dealers','publish','1',$ taxtype,$ geo,$ brands);对于custom_pre_get_posts(),我得到了缺少的参数2到7。我假设由于add_action ???
–user1609391
2012年12月19日在17:55
我假设您已将custom_pre_get_posts更改为接受其余参数。是的,由于add_action导致出现错误。 add_action使用单个参数(即$ query)调用此函数,您应将默认值赋予其他参数,以避免遗漏参数错误。像($ posttype = null,$ poststatus = null ...)这样可以通过add_action正确调用。
– M-R
2012-12-19 18:07
M-R谢谢您的答复。我阅读了添加操作,发现应该分配一个优先级和参数编号。所以我将添加动作更改为
add_action('pre_get_posts','custom_pre_get_posts',10,7);
然后在我的taxonomy.php页面中,我do_action('pre_get_post',$ query,'经销商”,“发布”,“ 1”,$ taxtype,$ geo,$ brands);
。但是我仍然遇到同样的错误。我不确定在哪里放置默认值。我尝试了google,但找不到参考。您能否给我更多有关如何处理此问题的信息?–user1609391
2012-12-19 19:02
感谢您的答复和示例。但是我想我应该在做一个新的wordpress查询时尝试使用pre_get_posts。我试图保存查询,但就我而言,这可能是不可能的。原因是您在参数中设置的所有参数,我想从我的taxonomy.php文件传递给函数。因此,取决于我在taxonomy.php中执行的条件,$ paidvalue =“ 1”可能是1或0。即使页面未加载,似乎pre_get_posts也会正确触发,即使我未在taxonomy.php文件中调用该函数也是如此。我看到这个正确吗?
–user1609391
2012年12月21日,0:56
该答案目前尚无意义。您将有效地覆盖$ wp_query对象内的任何值,事情将完全失败。除此之外,pre_get_posts将运行附加查询根本不是真的...
– kaiser
13年10月10日在15:04