我有以下查询,可通过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');

的方法

评论


非常感谢你的答复。这是非常有帮助的。一个简单的问题。我将函数放在主题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



#2 楼

延迟答案是最受好评的答案,它会打断您的查询,并且在某些主要问题上是不正确的。

主要的WP_Query及其过滤器

首先,WordPress内部使用query_posts() (不要在主题或插件中使用WP_Query周围的薄包装)来做WP_Query。该WP_Query充当主循环/查询。该查询将运行许多过滤器和操作,直到建立实际的SQL查询字符串为止。其中之一是pre_get_posts。其他的还有posts_clausesposts_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_queryclass 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的答案。

如果您有任何疑问,这是一个很好的资源。