5

I've been trying to run a search on user names by following the wordpress codex but it doesn't seem to work...

The following query, which is copied directly from the codex, returns 0 results. However, If I remove the meta_query (or 'search' parameter, depending on if i search for username or first name) then it returns results. Is this a bug with Wordpress?

Essentially, in spite of the codex and multiple over examples I've looked up explicitly stating that both 'search' and 'meta_query' can run together it doesn't appear to be the case. Can anyone confirm this for me?

$meta_search = 'Ross';

$qArgs = array (
    'order' => 'ASC',
    'orderby' => 'display_name',
    'search' => '*'.esc_attr( $meta_search ).'*',
    'meta_query' => array(
        'relation' => 'OR',
        array(
            'key'     => 'first_name',
            'value'   => $meta_search,
            'compare' => 'LIKE'
        ),
        array(
            'key'     => 'last_name',
            'value'   => $meta_search,
            'compare' => 'LIKE'
        ),
        array(
            'key' => 'description',
            'value' => $meta_search ,
            'compare' => 'LIKE'
        )
    )
);

$find_users = new WP_User_Query($qArgs);

Solution: As a result of the missing functionality here I've been forced to run 2 separate queries and merge them together. Far form ideal but in real time I cannot wait for a bug fix. So, for what its worth (which for the higher level devs out there will be minimal, but for intermediates will hopefully be useful) here's my work around -

// ORIGINAL QUERY
$qArgs = array('role' => 'subscriber','posts_per_page' => -1);

// SIMPLE SEARCH
$search1Args = array('search' => '*'.esc_attr($meta_search).'*');    
// merge search with original query
$s1Args = array_merge($qArgs, $search1Args);
// go fetch
$find_users_1 = new WP_User_Query($s1Args);

// META QUERY
$search2Args = array(
    'meta_query' => array(
    'relation' => 'OR',
    array(
        'key'     => 'first_name',
        'value'   => $meta_search,
        'compare' => 'LIKE'
    ),
    array(
        'key'     => 'last_name',
        'value'   => $meta_search,
        'compare' => 'LIKE'
    )
    )
);
// merge search with original query
$s2Args = array_merge($qArgs, $search2Args);
// go fetch
$find_users_2 = new WP_User_Query($s2Args);

// MERGE QUERIES
$find_out_1 = $find_users_1->get_results();
$find_out_2 = $find_users_2->get_results();
$found_users = array_merge_recursive($find_out_1, $find_out_2); // rebuild the returned users

$find_count_1 = $find_users_1->total_users;
$find_count_2 = $find_users_2->total_users;
$find_count = ($find_count_1 + $find_count_2); // rebuild the user count

// RECOMPILE
$find_users = $find_users_1;
$find_users->results = $found_users;
$find_users->total_users = $find_count;

As a warning I haven't considered pagination here and it would need considering if someone expected to use this on a site with a lot of users.

1 Answer 1

1

They seems to work together, but note the AND part between the search part and the meta query part, in the generated SQL query. I wonder if you expected OR instead?

Here are the generated SQL queries, for the two cases you mentioned:

Search + Meta Query:

SELECT DISTINCT SQL_CALC_FOUND_ROWS wp_users.* 
    FROM wp_users 
    INNER JOIN wp_usermeta 
        ON ( wp_users.ID = wp_usermeta.user_id ) 
    WHERE 1=1 
        AND 
        ( 
            (
                    wp_usermeta.meta_key = 'first_name' 
                AND CAST(wp_usermeta.meta_value AS CHAR) LIKE '%Ross%' 
            ) 
            OR 
            ( 
                    wp_usermeta.meta_key = 'last_name' 
                AND CAST(wp_usermeta.meta_value AS CHAR) LIKE '%Ross%' 
            ) 
            OR 
            (   
                    wp_usermeta.meta_key = 'description' 
                AND CAST(wp_usermeta.meta_value AS CHAR) LIKE '%Ross%'
            )
        ) 
        AND 
        (
               user_login LIKE '%Ross%' 
            OR user_nicename LIKE '%Ross%'
        ) 
    ORDER BY display_name ASC ;

Only Search:

SELECT SQL_CALC_FOUND_ROWS wp_users.* 
    FROM wp_users 
    WHERE 1=1 
        AND 
        (
               user_login LIKE '%Ross%' 
            OR user_nicename LIKE '%Ross%'
        ) 
    ORDER BY display_name ASC ;

Core check:

In the core we have the WP_User_Query::get_search_sql() method returning an AND part:

return ' AND (' . implode(' OR ', $searches) . ')';

and similarly in the WP_Meta_Query::get_sql_clauses() method, we have an AND part:

$sql['where'] = ' AND ' . $sql['where'];
3
  • I did absolutely expect it to be an OR conditional as an AND conditional would very rarely return a match. Surely this is an oversight from dev perspective.. Thank you for your research on the matter, its much appreciated.
    – Ant
    Commented Jul 8, 2015 at 8:34
  • Are you saying that this is bug from WordPress query itself? Do you have any alternative for this? I'm also encountering this problem as of the moment. Commented Feb 23, 2017 at 2:30
  • I think this is by design. You could use two queries like OP demonstrated. Then there are more hacky ways, like manually override the SQL with the pre_user_query hook and even extend the WP_User_Query class to your needs. @user1645213
    – birgire
    Commented Feb 23, 2017 at 9:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.