web-dev-qa-db-ja.com

いつ/なぜ '$ query-> get(' tax_query ');'を行いますか?空に戻る?

まずコード

function itsme_better_editions( $query ) {
    if ( $query->is_category() && $query->is_main_query() ) {
        $query->set( 'post_type', array( 'post' ) );

        // Get current tax query
        $tax_query = $query->get( 'tax_query' );

        $tax_query['relation'] = 'OR';

        $tax_query[] = array(
            'taxonomy' => 'category',
            'field' => 'slug',
            'terms' => 'intl',
            'operator' => 'IN'
        );

        $query->set( 'tax_query', $tax_query );
    }
    return $query;
}
add_filter( 'pre_get_posts', 'itsme_better_editions' );

$query->get( 'tax_query' );が空を返すか配列を返さないように見えることを除いて、それはすべて私には正しいようです。すなわち、以下の条件はtrueを返します。

if( !empty($tax_query) || is_array($tax_query) ) {
   // whatever
}

これは壊れている、後で気づいた

正しい投稿がアーカイブに表示されています。つまり、現在のカテゴリOR 'International(intl)'カテゴリのいずれかに属する投稿が一覧表示されています。それが私が欲しいものです。

しかし、オブジェクトという用語は「intl」カテゴリを指しています(タグアーカイブでも同じことが起こります。現在のタグを指す用語オブジェクトの代わりに、「intl」カテゴリを指しています)。たとえば、「UK(uk)」カテゴリアーカイブにアクセスすると、「UK」ではなく「International」と表示されます。

これは私がこれまでに気づいた問題のほんの一例です。他に何が壊れているのかわかりません。

この機能の何が問題になっていますか


PS: そして$query->get( 'tax_query' );は空または配列ではない値を返していたので、以下のように手動で埋めなければなりませんでした:

/*
 * Show posts assigned to 'International (intl)' Edition
 * in all editions.
 */
function itsme_better_editions( $query ) {
    if( $query->is_category() && $query->is_main_query() ) {

        $query->set( 'post_type', array( 'post' ) );

        // NOT WORKING!!!
        //$tax_query = $query->get( 'tax_query' );

        // Equivalent of original `$tax_query` START.
        $get_original_category = get_query_var( 'category_name' );
        $original_category = get_term_by( 'slug', $get_original_category, 'category' );
        if( $original_category && !is_wp_error( $original_category ) ) {
            $itsme_original_category = $get_original_category;
        }

        $tax_query[] = array(
            'taxonomy' => 'category',
            'field' => 'slug',
            'terms' => $original_category,
            'operator' => 'IN'
        );
        // Equivalent of original `$tax_query` END.

        $tax_query['relation'] = 'OR';

        $tax_query[] = array(
            'taxonomy' => 'category',
            'field' => 'slug',
            'terms' => 'intl',
            'operator' => 'IN'
        );

        $query->set( 'tax_query', $tax_query );
    }
    return $query;
}
add_filter( 'pre_get_posts', 'itsme_better_editions' );

または単にそのようにクエリを置き換えます。

/*
 * Show posts assigned to 'International (intl)' Edition
 * in all editions.
 */
function itsme_better_editions( $query ) {
    if( $query->is_category() && $query->is_main_query() ) {

        // Get original/actual category of the category archive
        $get_original_category = get_query_var( 'category_name' );
        $original_category = get_term_by( 'slug', $get_original_category, 'category' );
        if( $original_category && !is_wp_error( $original_category ) ) {
            $itsme_original_category = $get_original_category;
        }

        if( isset($itsme_original_category) ) {

            $query->set( 'post_type', array( 'post' ) );

            $query->set( "category_name", "{$itsme_original_category}, intl" );

        }

    }
}
add_action( 'pre_get_posts', 'itsme_better_editions' );

これはうまくいきますが、なぜ私はこうするべきなのでしょうか。 $tax_query = $query->get( 'tax_query' );は元のtax_queryを返すことになっていませんか?


問題の再現方法

1.イギリス(UK)とインターナショナル(intl)の2つのカテゴリを作成します。 2件の投稿を作成し、それらを「UK」のみに割り当てます。 1 'International'の下にあります。

現在、example.com/category/uk/は2件の投稿を表示しています。そしてexample.com/category/intl/は1を示します。

2.テーマのfunctions.phpに最初の関数(最初のコードブロック)を追加して、example.com/category/uk/にアクセスします。ページのカテゴリ名(<?php single_cat_title(); ?>)が 'International'と表示されているのがわかります。 なんで? 間違っていなければ、$ query-> get( 'tax_query');配列ではなく、空を返すようです。

3. functions.php内の関数を上記の2番目または3番目の関数に置き換えます。今ではすべてが想定通りに動作するはずです。

PS: はい、私は自分自身をデフォルトのテーマ(Twenty 13)でテストしましたが、それは持続します。それであなたは問題なくちゃんと問題を再現することができるでしょう。

3
its_me

メインクエリの$query->getは、パブリッククエリ変数、つまりURL経由でトリガーできる変数でのみ機能しますが、クエリのtax_queryプロパティに直接アクセスすることを妨げるものはありませんが、オブジェクトであることに注意してください WP_Tax_Query および現在のクエリされた分類法の引数は、そのオブジェクトのqueriesプロパティにあります。

そのプロパティにアクセスすると、関数内でget_term_byを使用して別のクエリを実行することを避けます。副作用として、single_cat_titleは正しいタイトルを出力します:

function itsme_better_editions( $query ) {

  if ( $query->is_category() && $query->is_main_query() ) {

    $query->set( 'post_type', array( 'post' ) );

    $tax_query_obj = clone $query->tax_query;

    $tax_query_obj->queries[] = array(
      'taxonomy' => 'category',
      'field' => 'slug',
      'terms' => 'intl',
      'operator' => 'IN'
    );

    $tax_query = array('relation' => 'OR');

    foreach ( $tax_query_obj->queries as $q ) {
      $tax_query[] = $q;
    }

    $query->set('tax_query', $tax_query);
  }

}

add_action( 'pre_get_posts', 'itsme_better_editions' );

実際には、管理クエリでもフィルタを実行していることに注意してください。そうでない場合は、最初のif条件付き関数内に&& ! is_admin()を追加します。

PS:ヒント:'pre_get_posts'を使用する場合、クエリは参照として渡されるため、add_actionの代わりにadd_filterを使用できますが、何も返しません。

6
gmazzap

クエリに渡された場合、$tax_query = $query->get( 'tax_query' );は元のtax_queryを返します。例えば:

function itsme_better_editions( $query ) {
  $query->set( 'post_type', array( 'post' ) );

  // Get current tax query
  $tax_query = $query->get( 'tax_query' );
  var_dump($tax_query); die;
}
add_action( 'pre_get_posts', 'itsme_better_editions' );

$t = new WP_Query(
  array(
    'post_type' => 'post',
    'tax_query' => array(
      array(
        'taxonomy' => 'category',
        'field' => 'slug',
        'terms' => 'intl',
        'operator' => 'IN'
      )
    )
  )
);

ただし、カテゴリアーカイブに$wp_queryをダンプする場合、またはメインクエリに対して同様のテストを実行する場合、既に発見したようにtax_queryはありません。これは、いくつかのデフォルトクエリでは、WP_Queryオブジェクトが tax_queryを構成する 他のクエリパラメータから pre_get_postsが実行されてからずっと後 のためです。 $tax_query = $query->get( 'tax_query' );が空なのはそのためです。

2
s_ha_dum