tax_query not working on main query

I’m using the following code to do a tax_query and it doesn’t seem to work anymore..

At some point it was working and for the life of me it wont, anymore.

Read More
<?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();
}

?>

Taxonomy is added like so:

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 );

In my footer.php I add this code:

$GLOBALS['wp_query']->request

I get this as a result when going to 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

The $pf_override variable shows $pf_override->site_terms to be set as an array of

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

Related posts

2 comments

  1. Well it seems after digging in to the code, tax_query is being blocked on single post/page pages which is why I’m running in to this issue.

    If you see the ability to run tax_query in all circumstances as beneficial, please voice your opinion on trac.

    See ticket here:
    http://core.trac.wordpress.org/ticket/24819

    I managed to get around this by duplicating the core code for singular posts and appending to the join and where clauses. The new code is as follows:

    <?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. I want give a simple solution.

    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
        }
      }
    }
    

    As extra benefit, changing $query->set( 'page_id', -1 ); with the id of a page specifically created is possible redirect visitors to a page you want, instead of force a 404 error.

    Hope it helps.

Comments are closed.