Filter admin post list with multiple filters; how to structure query object with logical AND operator

Refresh

April 2019

Views

0 time

1

I need assistance understanding how to structure the WP_query object to apply multiple criteria / filters.

In this case, I'm currently filtering the admin post list using two get variable, that should BOTH match the resulting posts list. I can get this to work fine for one variable but not both.

After the get variable is set, the following works perfectly to filter the admin post lists by a single get variable (labelled "Notification" in the get variable, and an ACF database key of "author_notified").

add_filter( 'parse_query', 'filter_admin',15 );

function filter_admin( $query ){
    global $pagenow;
    $type = 'post';
    if (isset($_GET['post_type'])) {
        $type = $_GET['post_type'];
    }
    if ( 'post' == $type && is_admin() && $pagenow=='edit.php' && isset($_GET['Notification']) && $_GET['Notification'] != '') {
        $query->query_vars['meta_key'] = 'author_notified';
        $query->query_vars['meta_value'] = $_GET['Notification'];
    }

}

This results in a query object where WP_query[query_vars][meta_key] and WP_query[query_vars][meta_value] target the desired subset of posts.

How should the query object be structured to target a subset of posts that matches two similar criteria simultaneously? Or more simply, how do I filter the admin posts lists by two criteria that must both be true?

I'm still pretty new to PHP/wordpress and unsure how to structure query objects. Any help or suggestions would be much appreciated!

P.J

1 answers

1

Solved, many thanks to troubleshooting tips from @FluffyKitten.

The WP_query object should be structured as follows to achieve multiple filters to the admin posts list. Essentially, ACF fields can be added with logical operators to WP_query[query_vars][meta_query]:

        [meta_query] => Array
            (
                [relation] => AND
                [0] => Array
                    (
                        [key] => author_notified
                        [value] => 1
                        [compare] => =
                        [type] => NUMERIC
                    )

                [1] => Array
                    (
                        [key] => recommended_decision
                        [value] => 0
                        [compare] => =
                        [type] => CHAR
                    )

            )

This query object structure can be accomplished with a function as follows, assuming GET variables named "Notification" and "Recommendation" have already been set elsewhere:

add_filter( 'parse_query', 'posts_filter2',15 );

function posts_filter2( $query ){
   global $pagenow;
   $type = 'post';
   if (isset($_GET['post_type'])) {
       $type = $_GET['post_type'];
   }
   if ( 'post' == $type && is_admin() && $pagenow=='edit.php') {

        $queryParamsCounter = 0;
        if (isset( $_GET['Notification'] ) && $_GET['Notification'] != '')
        {
          $notification = (int)$_GET['Notification'];
          $queryParamsCounter++;
        }
        if (isset( $_GET['Recommendation'] ) && $_GET['Recommendation'] != '')
        {
          $queryParamsCounter++;
          $recommendation = $_GET['Recommendation'];
        }

        $meta_query = array();

        if ($queryParamsCounter > 1) {
          $meta_query['relation'] = 'AND';
        }

        if (isset($notification)) {
          $meta_query[] =       array(
            'key' => 'author_notified',
            'value'    => $notification,
            'compare' => '=',
            'type'    => 'NUMERIC',  
          );
        }
        if (isset($recommendation)) {
          $meta_query[] = array(
            'key'     => 'recommended_decision',
            'value'   => $recommendation,
            'compare' => '=',
            'type'    => 'CHAR',
          );
        }

        $query->set( 'meta_query', $meta_query);

    }
}

Note that if only one filter is selected the relation key should not be used.

I hope this helps others facing the same challenge!

P.J