Search code examples
phpwordpressmeta-query

What is the best way to append additional 'meta_query' array to WP_Query conditionally


I have the following function:

function returnD($p, $t1, $t2, $t3) {
    $args = array(
        'post_type' => $p,
        'posts_per_page' => -1,
        'meta_query'    => array(
            array(
                'key'     => $t1,
                'value'   => 'up',
                'compare' => '=',
            )
        ) 
    );
    $loop = new WP_Query( $args );
    
    return $loop;
}

How can I modify the $args meta_query so that if

$t1, $t2, $t3 have no values there are no meta_query added

otherwise for each $t#, an array is added to meta_query.

I am just trying to make it dynamic because not every call will have all three $t#.

How can I achieve it?


Solution

  • You can dynamically build the meta_query array depending on the values that are passed in. In the code below,

    1. we build a sub-array for each $t# parameter passed in
    2. if we have any $t# parameters then we use these arrays to build our meta query.
    3. we build the $args array without the meta_query arg
    4. finally, if we have a meta_query array, add it into our $args

    The full function is below, and the code is commented:

    function returnD($p, $t1, $t2, $t3) {
       
        // 1. if the $t# parameters have a value, create the meta_query sub-array for that value
        if ($t1) $t1query =  array( 'key'=> $t1, 'value' => 'up', 'compare' => '='  );
        if ($t2) $t2query =  array( 'key'=> $t2, 'value' => 'up', 'compare' => '='  );
        if ($t3) $t3query =  array( 'key'=> $t3, 'value' => 'up', 'compare' => '='  );
    
        // 2. if any of the $t# parameters have an array, then create our meta_query
    
        $meta_query = array( 'relation' => 'AND');    // change this to OR if required
            if ($t1query) $meta_query[] = $t1query;
            if ($t2query) $meta_query[] = $t2query;
            if ($t3query) $meta_query[] = $t3query;
        }
    
        // 3. set up your default args for this query
        $args = array(
            'post_type' => $p,
            'posts_per_page' => -1,
        );
    
        // 4. only add the meta query if one exists
        if ($meta_query)
            $args['meta_query'] = $meta_query;
    
        $loop = new WP_Query( $args );
        
        return $loop;
    }
    

    Note that this isn't tested, but the basic idea is there. Also, you didn't say if this is an AND or OR meta_query so I've built it using AND, but you can change as required.

    UPDATE: If you have a default meta_query, then you can add it to the meta_query array and args as normal. Then there is no need for the conditional statements to check if ($meta_query) in step 4 above.

    function returnD($p, $t1, $t2, $t3) {
       
        // 1. if the $t# parameters have a value, create the meta_query sub-array for that value
        if ($t1) $t1query =  array( 'key'=> $t1, 'value' => 'up', 'compare' => '='  );
        if ($t2) $t2query =  array( 'key'=> $t2, 'value' => 'up', 'compare' => '='  );
        if ($t3) $t3query =  array( 'key'=> $t3, 'value' => 'up', 'compare' => '='  );
    
        // 2. Create our meta_query. 
        $meta_query = array(
             'relation' => 'AND',    // change this to OR if required
             // add default meta_query array(s) here
             array( 'key' => 'color', 'value' => 'blue', 'compare' => 'NOT LIKE'),
        );
    
        if ($t1query) $meta_query[] = $t1query;
        if ($t2query) $meta_query[] = $t2query;
        if ($t3query) $meta_query[] = $t3query;
    
        // 3. set up your default args for this query
        $args = array(
            'post_type' => $p,
            'posts_per_page' => -1,
            'meta_query' => $meta_query
        );
    
        $loop = new WP_Query( $args );        
        return $loop;
    }