1

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?

Si8
  • 9,141
  • 22
  • 109
  • 221

1 Answers1

2

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;
}
FluffyKitten
  • 13,824
  • 10
  • 39
  • 52
  • Thanks, I will test it out :) – Si8 Sep 02 '20 at 13:12
  • @Si8 Let me know if you have any problems! I've done this many times before so it is possible, just might need to tweak the code a bit. FYI I was also thinking: OR is probably better than AND for testing anyway - AND might return no results depending on the parameters so it might be hard to tell if its working. OR would return more results so at least you can see if the query runs :) – FluffyKitten Sep 02 '20 at 13:28
  • Awesome. Thanks for your input. BTW wouldn't the `if` statement be not entirely accurate? if `$t1` but no `$t2` it would still try to fill in `$t2`? – Si8 Sep 02 '20 at 14:42
  • 1
    @Si8 Oops! Those first 3 `if` statements were supposed to create 3 different arrays - I copied & pasted the first line and forgot to change all the variable names - I've fixed that in the code now. As for the `if ($t1 || $t2 || $t3)` - if the arrays are empty, they won't have any effect on the `$meta_query` - it will be just like we didn't even try to add them. – FluffyKitten Sep 02 '20 at 14:48
  • That makes perfect sense. Thanks! – Si8 Sep 02 '20 at 14:51
  • @Si8 Just in case you are having problems with the "empty" arrays, I've added an alternative way to build the `meta_query` array. There was also an extra `)` in the code for the `$args`. Let me know if this is working for you! – FluffyKitten Sep 02 '20 at 15:51
  • Just a quick question, can I add a default `meta_query` in the default `args`? – Si8 Sep 02 '20 at 15:51
  • @Si8 Yes, just add it to the `$meta_query` array the same as you would normally. If you do this, make sure you remove the `if ($t1 || $t2 || $t3)`... we only needed that because it was possible that we would have no meta_query. Now that you have a default meta_query, you're going to build it one way or another – FluffyKitten Sep 02 '20 at 15:54
  • 1
    @Si8 FYI I've updated my answer to show how to do that. Let me know if it works for you! – FluffyKitten Sep 02 '20 at 16:01
  • 1
    Thanks!!! I was able to use what you wrote and tweak it a bit to fit my need. I upvoted and +1 your answer. – Si8 Sep 03 '20 at 00:41
  • I am having a little problem. If I only want to send the value for the last parameters, do I call like this: `$get_result = returnD('', '', '', 'yes')`? It seems like that's not working because `yes` should only return active items but it's returning all the items. – Si8 Sep 10 '20 at 13:47
  • Also the `meta_query` array is built like this: `Array ( [relation] => AND [0] => [1] => [2] => [3] => no ) array(3) { ["post_type"]=> string(7) "prod" ["posts_per_page"]=> int(-1) ["meta_query"]=> array(5) { ["relation"]=> string(3) "AND" [0]=> NULL [1]=> NULL [2]=> NULL [3]=> string(2) "no" } }` which doesn't make sense. – Si8 Sep 10 '20 at 13:52
  • Your "middle" code worked for me to create the `meta_query` :) – Si8 Sep 10 '20 at 14:00
  • @Si8 Glad you got the metaquery working! I'll edit my answer to make use the "middle" code. Your code to pass just the last parameter looks fine`$get_result = returnD(, '', '', 'yes')?`, the only think you might be missing is the post type in the first parameter if you want to filter by it? – FluffyKitten Sep 10 '20 at 14:45
  • It's one post type so didn't feel the need to make it that dynamic :). Thanks for the edit, the original post added the meta query with a NULL which may have thrown off the WP_Query totally. But it's all good, Thanks for the help!!! – Si8 Sep 10 '20 at 20:13
  • @FluffyKitten I tried meta query statically it works but when I tried to build meta query options dynamically it's not working for current scenario. On current page I got serveral parameters from GET method and according to it I need to create meta_query arguments array. I tried to create arguments array as per method listed above, but no success. So can you please support me. – Ankur21 Dec 20 '22 at 10:55
  • Hi @Ankur21, Stack Overflow isn't a support forum, it's a question and answer site. If you have having a different problem, then you should add your own question showing your code that is not working for you and the specific details of the issue. But as a starting point to debug the problem, have you tried doing `print_r` of your `$meta_query` and `$args` arrays to make sure they are being created properly? The most likely issue is that these are not being created correctly. If you can't figure out what is wrong, then include the output in your new question. Good luck! – FluffyKitten Dec 22 '22 at 04:02