Search code examples
wordpress

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


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!


Solution

  • 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!