从wordpress.stackexchange重新发布:
我运行一个博客网站,其中包含作者的帖子,如果搜索类似于作者姓名或搜索词包含在故事中,我实施的搜索会返回结果。我正在运作并且正确地返回了与搜索匹配的作者,但现在搜索每次都返回每个用户。
我怀疑它与WP_User_query since
有关,因为该功能在4.2中已更新,但我不知道如何将其更改为兼容。
以下是搜索代码:
add_filter('user_search_columns', 'user_search_columns_bd' , 10, 3);
function user_search_columns_bd($search_columns, $search, $this){
if(!in_array('display_name', $search_columns)){
$search_columns[] = 'display_name';
}
return $search_columns;
}
add_filter( 'get_meta_sql', 'user_meta_filter', 10, 6 );
function user_meta_filter( $sql, $queries, $type, $primary_table, $primary_id_column, $context ){
if ( $type !== 'user' ){
return $sql;
}
if ( ! isset( $context->query_vars['meta_query']['replace_and'] ) || $context->query_vars['meta_query']['replace_and'] !== true ){
return $sql;
}
$sql['where'] = preg_replace('/AND/', 'OR', $sql['where'], 1);
return $sql;
}
$args = array(
'search' => $s,
'search_columns' => array( 'user_login', 'user_email'),
'meta_query' => array(
'relation' => 'OR',
'replace_and' => true,
array(
'key' => 'first_name',
'value' => $s,
'compare' => 'LIKE'
),
array(
'key' => 'last_name',
'value' => $s,
'compare' => 'LIKE'
)
)
);
// The Query
$user_query = new WP_User_Query( $args );
编辑:
数组形式的相关sql:
Array ( [join] => INNER JOIN wp_usermeta ON ( wp_users.ID = wp_usermeta.user_id ) [where] => OR ( ( wp_usermeta.meta_key = 'first_name' AND CAST(wp_usermeta.meta_value AS CHAR) LIKE '%Search%' ) OR ( wp_usermeta.meta_key = 'last_name' AND CAST(wp_usermeta.meta_value AS CHAR) LIKE '%Search%' ) ) )
我不太确定为什么这个sql在最新更新中不再有效。它似乎格式正确,但它仍然会返回所有作者。
答案 0 :(得分:1)
看起来我是对的(请参阅评论评论):我有可能在更新之前和之后测试查询,并且它已更改:
# BEFORE
SELECT DISTINCT SQL_CALC_FOUND_ROWS wp_users.* FROM wp_users INNER JOIN wp_usermeta ON ( wp_users.ID = wp_usermeta.user_id ) INNER JOIN wp_usermeta AS mt1 ON ( wp_users.ID = mt1.user_id ) WHERE 1=1 AND (user_login LIKE 'test' OR user_email LIKE 'test' OR display_name LIKE 'test') OR (
(
(
( wp_usermeta.meta_key = 'first_name' AND CAST(wp_usermeta.meta_value AS CHAR) LIKE '%test%' )
OR
( wp_usermeta.meta_key = 'last_name' AND CAST(wp_usermeta.meta_value AS CHAR) LIKE '%test%' )
)
AND
mt1.meta_key = 'wp_6_capabilities'
)
) ORDER BY user_login ASC
# AFTER
SELECT DISTINCT SQL_CALC_FOUND_ROWS wp_users.* FROM wp_users INNER JOIN wp_usermeta ON ( wp_users.ID = wp_usermeta.user_id ) INNER JOIN wp_usermeta AS mt1 ON ( wp_users.ID = mt1.user_id ) WHERE 1=1 OR (
(
(
( wp_usermeta.meta_key = 'first_name' AND CAST(wp_usermeta.meta_value AS CHAR) LIKE '%test%' )
OR
( wp_usermeta.meta_key = 'last_name' AND CAST(wp_usermeta.meta_value AS CHAR) LIKE '%test%' )
)
AND
mt1.meta_key = 'wp_6_capabilities'
)
) AND (user_login LIKE 'test' OR user_email LIKE 'test' OR display_name LIKE 'test') ORDER BY user_login ASC
所以在你的代码中使用这一行
$sql['where'] = preg_replace('/AND/', 'OR', $sql['where'], 1);
您正在使用AND
更改查询中找到的第一个OR
,但正如您现在所看到的那样,它定位的是错误的。{/ p>
事实上现在条件是WHERE 1=1 OR ...
,就像说ALWAYS
。 :)
正如我之前在评论中所说,您需要定位正确的AND
,但请注意,订单可能会再次发生变化。
<强>更新强>
不幸的是,没有最终的方法可以做到这一点,因为它不是原生的(我们希望它很快会被添加),所以你需要依靠改变正确的AND
。
也许找到一种适用于查询(旧版和新版)的方法,为此你需要更改过滤器钩子:使用pre_user_query
:
add_action('pre_user_query', 'my_custom_users_search');
function my_custom_users_search( $args ) {
if( isset( $args->query_vars['meta_query']['replace_and'] ) && $args->query_vars['meta_query']['replace_and'] )
$args->query_where = str_replace(') AND (', ') OR (', $args->query_where);
}