WP_User_Query ignoring 'meta_query' arguments

So, I'm trying to do a query on 'members' based on some inputs from a form using AJAX.

The thing is that when searching for a 'role' I get the expected result. But once I try to look for other meta values, the return bring all members in the DB.

I tried in a bunch of ways but I either get the result I just said, or I simply get no result at all (even with the role)

Here is my PHP code that is inside 'functions.php':

function my_ajax_filter_search_callback() {
    header(Content-Type: application/json);

    if(isset($_GET['name'])  !empty($_GET['name'])) {
        $name = sanitize_text_field( $_GET['name'] );
        $searchName = array(
            'search' = $name,
            'search_columns' = array( 'first_name' ),
            'compare' = 'LIKE'
        );
        $searchName[] = array(
            'search' = $name,
            'search_columns' = array( 'last_name' ),
            'compare' = 'LIKE'
        );
    }

    if(isset($_GET['keywords'])  !empty($_GET['keywords'])) {
        $keywords = sanitize_text_field( $_GET['keywords'] );
        $searchKeywords = array(
            'key' = 'keywords',
            'value' = $keywords,
            'compare' = 'LIKE'
        );
    }

    if(isset($_GET['countries'])  !empty($_GET['countries'])) {
        $country = sanitize_text_field( $_GET['countries'] );
        $searchCountry = array(
            'key' = 'country',
            'value' = $country,
            'compare' = '='
        );
    }

    if(isset($_GET['disciplines'])  !empty($_GET['disciplines'])) {
        $discipline = sanitize_text_field( $_GET['disciplines'] );
        $searchDiscipline = array(
            'key' = 'disciplines',
            'value' = $discipline,
            'compare' = '='
        );
    }

    if(isset($_GET['roles'])  !empty($_GET['roles'])) {
        $role = sanitize_text_field($_GET['roles']);
    }

    $args = array(
        'role' = $role,
        'meta_query' = array(
            'relation' = 'AND',
            array(
                'relation' = 'OR',
                $searchName
            ),
            $searchKeywords,
            $searchCountry,
            $searchDiscipline
        )
    );


    $user_query = new WP_User_Query( $args );

    if ( !empty( $user_query-get_results() ) ) {
        $results = array();
        $count = 0;
        foreach ( $user_query-get_results() as $member ) {
            $member_info = get_userdata( $member-ID );
            $results[] = array(
                'id' = $member-ID,
                'name' = $member_info-first_name .' '.$member_info-last_name,
                'role' = $member_info-roles,
                'keywords' = $member_info-keywords,
                'country' = $member_info-country,
                'disciplines' = $member_info-disciplines,
            );

            $count++;
        }

        echo json_encode($results);

    }

    wp_die();
}

I even tried creating all the structure for the arguments in the same place to be sure that there is not an extra 'array' or something, same result.

Here is an example of my return when looking for a name:

And here is an example of my return when looking for a role:

The fields I'm trying to search were added with the plugin Paid Memberships Pro and that info is located on the 'wp_usermeta' table. Here is a print of one of those fields 'discipline':

Topic wp-user-query meta-query ajax Wordpress

Category Web


But once I try to look for other meta values, the return bring all members in the DB.

Are you sure the meta other than name did not work, i.e. all members/users were returned?

Because as I could see it, for your keywords, country and disciplines meta, so long as your compare value is good, then the meta query would work and only members having the specified metadata that would be returned.

For example, your compare for the keywords meta is LIKE, so if you searched for foo and there were members with foo (regardless of the letter case) in their keywords meta, then only those members would appear in the user query's results.

So make sure your compare value is good, particularly for the disciplines meta which I supposed contains multiple values that are separated using a comma (e.g. discipline 1, discipline 2) and yet, your compare is = which means an exact-match search that's commonly used for meta values with a single value.

Now as for the first/last name search, I noticed the following issues:

  1. Your meta query clauses are missing key (meta key/name) and value (meta value), and WordPress ignored the meta query because the meta key is not specified. Also, search and search_columns are not valid keys for clauses in a meta query.

  2. The array( 'relation' => 'OR', $searchName ) produces array( 'relation' => 'OR', array( 'search' => ..., ..., ..., array( ... ) ) ) instead of array( 'relation' => 'OR', array( ... ), array( ... ) ), so your meta query wouldn't work properly even if you specified the correct meta key.

  3. You should use $searchName[] = array( to add the first_name array, like you did with the last_name array.

So, try defining the $searchName like this:

$searchName = array(
    'relation' => 'OR',
);

$searchName[] = array(
    'key'     => 'first_name', // meta key
    'value'   => $name,        // meta value
    'compare' => 'LIKE'
);

$searchName[] = array(
    'key'     => 'last_name', // meta key
    'value'   => $name,       // meta value
    'compare' => 'LIKE'
);

And then in $args, add meta_query like so:

'meta_query' => array(
    'relation' => 'AND',
    $searchName,
    $searchKeywords,
    $searchCountry,
    $searchDiscipline
)

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.