web-dev-qa-db-ja.com

tax_queryがメインクエリで機能しない

Tax_queryを実行するために次のコードを使用していますが、動作しないようです。

ある時点でそれは機能していたし、私の人生のためにそれはもう、文句を言わない。

<?php

global $pf_override;

class PF_override {

    public $site_terms = array();

    function __construct() {

        // add filters
        add_filter( 'init', array( &$this, 'populates_site_terms' ) );
        add_filter( 'pre_get_posts', array( &$this, 'filter_query' ) );
    }

    function populates_site_terms() {

        // my actual function does some processing and
        // checks caches and combines IDs from multiple
        // different sources here and then sets site_terms 

        $this->site_terms = array( 1, 2, 3 );
    }

    function filter_query( $query ) {

        // not the main query?
        if ( !$query->is_main_query() ) {
            return $query;
        }

        // have terms to filter by?
        if ( !empty( $this->site_terms ) ) {

            // construct tax_query
            $tax_query = array(
                'taxonomy'  => 'site_category',
                'field'     => 'id',
                'terms'     => $this->site_terms,
                'operator'  => 'IN'
                );

            // this needs to be an array of arrays
            $taxquery = array(
                $tax_query
            );

            // set this..
            $query->set( 'tax_query', $taxquery );
        }

        // return new query object
        return $query;
    }
}

// not the admin? init class
if ( !is_admin() ) {
    $pf_override = new PF_override();
}

?>

分類法は次のように追加されています。

function PF_register_post_type() {
    $labels = array(
        'name'              => _x( 'Site Category', 'taxonomy general name' ),
        'singular_name'     => _x( 'Site Category', 'taxonomy singular name' ),
        'search_items'      => __( 'Search Site Categories' ),
        'all_items'         => __( 'All Site Categories' ),
        'parent_item'       => __( 'Parent Site Category' ),
        'parent_item_colon' => __( 'Parent Site Category:' ),
        'edit_item'         => __( 'Edit Site Category' ),
        'update_item'       => __( 'Update Site Category' ),
        'add_new_item'      => __( 'Add New Site Category' ),
        'new_item_name'     => __( 'New Site Category Name' ),
        'menu_name'         => __( 'Site Category' ),
    );

    $args = array(
        'hierarchical'      => true,
        'labels'            => $labels,
        'show_ui'           => true,
        'show_admin_column' => true,
        'query_var'         => true,
        'rewrite'           => array( 'slug' => 'sitecat' ),
    );

    register_taxonomy( 'site_category', array( 'post', 'page', 'attachment', 'revision', 'nav_menu_item' ), $args );
}

add_action( 'init', 'PF_register_post_types', 1 );

私のfooter.phpに私はこのコードを追加します:

$GLOBALS['wp_query']->request

Mydomain.com/testingに行くと私は結果としてこれを得る:

SELECT wp_posts.* FROM wp_posts  WHERE 1=1  AND wp_posts.post_name = 'testing' AND wp_posts.post_type = 'post' ORDER BY wp_posts.post_date DESC

$ pf_override変数は$ pf_override-> site_termsが以下の配列として設定されることを示します。

array( [0] => 1, [1] => 2, [2] => 3 )
1
Playforward

コードを掘り下げた後で、tax_queryが単一の投稿/ページページでブロックされているようです。

すべての状況でtax_queryを実行できることが有益であると思われる場合は、tracについてご意見をお寄せください。

こちらのチケットを参照してください。 http://core.trac.wordpress.org/ticket/24819

私はこれを回避するために、特異な投稿のためのコアコードを複製し、joinとwhere句に追加しました。新しいコードは次のとおりです。

<?php

global $pf_override;

class PF_override {

    public $site_terms = array();

    public $sql_join    = '';
    public $sql_where   = '';

    function __construct() {

        // add filters
        add_filter( 'init', array( &$this, 'populates_site_terms' ) );
        add_filter( 'pre_get_posts', array( &$this, 'filter_query' ) );
        add_filter( 'posts_join', array( &$this, 'filter_join' ) );
        add_filter( 'posts_where', array( &$this, 'filter_where' ) );
    }

    function populates_site_terms() {

        // my actual function does some processing and 
        // checks caches and combines IDs from multiple 
        // different sources here and then sets site_terms 

        $this->site_terms = array( 1, 2, 3 );
    }

    function filter_query( $query ) {

        // not the main query?
        if ( !$query->is_main_query() ) {
            return $query;
        }

        // have terms to filter by?
        if ( !empty( $this->site_terms ) ) {

            // construct tax_query
            $tax_query = array(
                'taxonomy'  => 'site_category',
                'field'     => 'id',
                'terms'     => $this->site_terms,
                'operator'  => 'IN'
                );

            // this needs to be an array of arrays
            $taxquery = array(
                $tax_query
            );

            // set this..
            $query->set( 'tax_query', $taxquery );

            if ( $query->is_singular ) {

                global $wpdb;

                $q = &$query->query_vars;

                $q['suppress_filters'] = false;

                $query->parse_tax_query( $q );

                $clauses = $query->tax_query->get_sql( $wpdb->posts, 'ID' );

                $this->sql_join     .= $clauses['join'];
                $this->sql_where    .= $clauses['where'];
            }
        }

        return $query;
    }

    function filter_join( $join ) {

        if ( !empty( $this->sql_join ) ) {
            $join .= $this->sql_join;
        }

        return $join;
    }

    function filter_where( $where ) {

        if ( !empty( $this->sql_where ) ) {
            $where .= $this->sql_where;
        }

        return $where;
    }
}

// not the admin? init class
if ( !is_admin() ) {
    $pf_override = new PF_override();
}

?>
2
Playforward

私は簡単な解決策を挙げたいと思います。

add_action('pre_get_posts', 'filter_query');

function filter_query( $query ) {
  // **PLEASE NOTE**
  // $this->site_terms refers specifically to logic in the question
  if ( $query->is_main_query() && $query->is_singular && ! empty( $this->site_terms ) ) {
    $site = get_queried_object();
    $terms = wp_get_object_terms($site->ID, 'site_category', array('fields' => 'ids') );
    if ( empty($terms) || empty( array_intersect($terms, $this->site_terms) ) ) {
        $query->set( 'page_id', -1 ); // 404
    }
  }
}

特別な利点として、特別に作成されたページのIDを使用して$query->set( 'page_id', -1 );を変更すると、404エラーを強制するのではなく、必要なページに訪問者をリダイレクトすることができます。

それが役に立てば幸い。

1
gmazzap