Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I query taxonomy OR custom field in Wordpress at the same time?

Tags:

wordpress

I need to query wordpress posts returning results that could be matched either by the category OR custom field. Using the below code only returns results if they are matched by the category AND custom field. I need to find matches where it could be matched by either query, so an "OR" result but doesn't seem to work.

Can anyone help?

$args =  array(
'post_type' => 'post',
'tax_query' => array(
'relation' => 'OR',
    array(
        'taxonomy'  => 'category',
        'field'     => 'slug',
        'terms' => array( 'arts','food' ),
        'operator'  => 'IN'
    )
),
'meta_query' => array(
   'relation' => 'OR',
    array(
        'key' => 'birth_city',
        'value' => 'London',
        'compare' => 'IN',
      ),
   )
);
like image 515
user3452572 Avatar asked Mar 24 '14 14:03

user3452572


People also ask

What is meta query in WordPress?

WP_Meta_Query is a helper that allows primary query classes, such as WP_Query and WP_User_Query, to filter their results by object metadata, by generating JOIN and WHERE subclauses to be attached to the primary SQL query string.

What is Meta_value?

The meta_value argument queries post that have the value you define. The meta_value argument is used for string values. This example will query any posts with a custom meta field that has the value “data1”. $args = array( 'meta_value' => 'data1' ); You can also combine the two.

How do I create a custom field value in WordPress post?

First, you need to edit the post or page where you want to add the custom field and go to the custom fields meta box. Next, you need to provide a name for your custom field and then enter its value. Click on the Add Custom Field button to save it.


1 Answers

Version 0.2

Here's a simplification of my previous answer - I hope you don't mind me adding it as a new answer, to avoid confusion with my previous one.

Here I use the WordPress functions get_meta_sql() and get_tax_sql(), to modify the WHERE part of the SQL generated by WP_Query():

 /**
 * Class WPSE_OR_Query 
 * 
 * Add a support for (tax_query OR meta_query) 
 *
 * @version 0.2
 * @link http://stackoverflow.com/a/22633399/2078474
 *
 */
class WPSE_OR_Query extends WP_Query 
{       
    protected $meta_or_tax  = FALSE;
    protected $tax_args     = NULL;
    protected $meta_args    = NULL;

    public function __construct( $args = array() )
    {
        add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ), 999 );
        add_filter( 'posts_where',   array( $this, 'posts_where' ),   999 );
        parent::__construct( $args );
    }
    public function pre_get_posts( $qry )
    {       
        remove_action( current_filter(), array( $this, __FUNCTION__ ) );            
        // Get query vars
        $this->meta_or_tax = ( isset( $qry->query_vars['meta_or_tax'] ) ) ? $qry->query_vars['meta_or_tax'] : FALSE;
        if( $this->meta_or_tax )
        { 
            $this->tax_args  = ( isset( $qry->query_vars['tax_query'] ) )  ? $qry->query_vars['tax_query']  : NULL;
            $this->meta_args = ( isset( $qry->query_vars['meta_query'] ) ) ? $qry->query_vars['meta_query'] : NULL;
        }
    }
    public function posts_where( $where )
    {       
        global $wpdb;       
        $field = 'ID';
        remove_filter( current_filter(), array( $this, __FUNCTION__ ) );    

        // Construct the "tax OR meta" query
        if( $this->meta_or_tax && is_array( $this->tax_args ) &&  is_array( $this->meta_args )  )
        {
            // Tax query
            $sql_tax = get_tax_sql( $this->tax_args, $wpdb->posts, $field );            

            // Meta query
            $sql_meta = get_meta_sql( $this->meta_args, 'post', $wpdb->posts, $field );

            // Modify the 'where' part          
            if( isset( $sql_meta['where'] ) && isset( $sql_tax['where'] ) )
            {
                $where  = str_replace( array( $sql_meta['where'], $sql_tax['where'] ) , '', $where );
                $where .= sprintf( ' AND ( %s OR  %s ) ', substr( trim( $sql_meta['where'] ), 4 ), substr( trim( $sql_tax['where'] ), 4 ) );              
            }
        }   
        return $where;
    }
}
like image 53
birgire Avatar answered Sep 20 '22 05:09

birgire