web-dev-qa-db-ja.com

Pre Get PostsまたはWP_Queryを使用する必要があります

私はquery_brands_geo('dealers', 'publish', '1', $taxtype, $geo, $brands);を介して私のtaxonomy.phpテンプレートで呼び出す次のクエリを持っています

この機能は完璧に機能します。しかし、クエリポストのためのコーデックスを読んだ後、それはデフォルトクエリを変更するための好ましい方法として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); 
} 
29
user1609391

pre_get_postsは同じクエリを実行するので、両方とも同じ時間がかかります。しかし、pre_get_postsアクションを利用すると、1つ以上の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');
14
M-R

最も支持された回答はクエリを中断し、いくつかの主要な点で単に真実ではないため、遅い回答です。

mainWP_Queryおよびそのフィルター

まず、WordPressは内部的にquery_posts()を使用します(WP_Queryの薄いラッパーは使用しないでくださいテーマまたはプラグインで)WP_Queryを実行します。このWP_Queryはメインループ/クエリとして機能しています。このクエリは、実際のSQLクエリ文字列が構築されるまで、多くのフィルターとアクションを実行します。それらの1つはpre_get_postsです。その他はposts_clausesposts_whereなどです。これらはalsoクエリ文字列構築プロセスをインターセプトできます。

コア内部で何が起こるかを詳しく見る

WordPressはwp()関数(wp-includes/functions.php内)を実行し、$wp->main()を呼び出します($wpwp-includes/class-wp.phpで定義されているクラスWPのオブジェクトです)。これは、WordPressに次のことを伝えます。

  1. WP->parse_request()を使用してURLをクエリ仕様に解析します。詳細は以下をご覧ください。
  2. $wp_query->parse_query()$wp_queryclass WP_Queryのオブジェクトであり、wp-includes/query.phpで定義されています)を使用して、Conditional Tagで使用されるすべてのis_変数を設定します。この関数の名前にもかかわらず、この場合、WP_Query->parse_queryは実際には解析を行いません。これは、WP->parse_request()によって事前に行われるためです。
  3. 関数WP_Query-> get_posts()で、クエリ仕様をMySQLデータベースクエリに変換し、データベースクエリを実行して投稿のリストを取得します。 WordPressループで使用される投稿を$ wp_queryオブジェクトに保存します。

ソース Codex

結論

メインクエリを本当に変更する場合は、さまざまなフィルターを使用できます。単に$query->set( 'some_key', 'some_value' );を使用してchangeデータを使用するか、$query->get( 'some_key' );を使用してretrieve条件付きチェックを行うデータ。これにより、SQLクエリのみalteringであるため、2番目のクエリを実行する必要がなくなります。

additionalクエリを実行する必要がある場合は、WP_Queryオブジェクトを使用します。これにより、DBに別のクエリが追加されます。

答えは例で常にうまく機能するので、ここであなたは本当に素晴らしいものを1つ手に入れました(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'";
    }
}

その後、次の例に示すように、second/ additionalクエリを実行できます。後でクエリをリセットすることを忘れないでください。

$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;
10
kaiser

WP_query()、query_posts()およびpre_get_posts を使用する場合。

あなたが心に疑いを持っているならば、それは素晴らしいリソースです。

6
fischi