WordPress自定义文章类型REST API中meta_query过滤参数不生效问题
问题原因
这个问题是WordPress 5.7+版本中REST API查询参数处理的两个已知特性导致的:
- 你使用
$args = $args + $meta_query的数组合并方式存在缺陷:PHP数组的加号运算符只会保留左侧数组中不存在的键,如果原$args中已经存在meta_query参数(哪怕是空值),你自定义的meta_query就不会被合并进去,就算调试时打印的结构看起来正确,也可能被后续默认处理逻辑覆盖。 - WordPress 5.7开始REST API内部对
WP_Query的meta相关参数做了更严格的校验,通过rest_{$post_type}_query钩子注入的meta_query如果没有和原有参数做递归合并,很容易被默认逻辑忽略。
解决方法
首先把你合并参数的代码替换成递归合并逻辑,兼容原有meta_query参数:
将原有代码:
$meta_query = array( 'meta_query' => $meta_query_args ); $args = $args + $meta_query; // TODO looks like meta_query is not working here
替换为:
// 合并原有meta_query和自定义的查询条件 if ( ! empty( $args['meta_query'] ) ) { // 原有查询条件和新条件默认用AND关系拼接 $args['meta_query'] = array_merge_recursive( array( 'relation' => 'AND' ), $args['meta_query'], $meta_query_args ); } else { $args['meta_query'] = $meta_query_args; }
如果修改后还是不生效,可以把钩子优先级从99调整到999,避免被其他插件/主题的同钩子逻辑覆盖:
add_filter( 'rest_course_query', 'chld_thm_post_meta_request_params', 999, 2 );
如果以上方法都不生效,可以改用兼容性更强的pre_get_posts钩子实现:
add_action( 'pre_get_posts', function( $query ) { // 只针对REST接口的course自定义文章查询生效 if ( defined( 'REST_REQUEST' ) && REST_REQUEST && $query->get( 'post_type' ) === 'course' ) { $request = $GLOBALS['wp']->query_vars; $meta_query_args = array( 'relation' => 'AND' ); // 复制你原来的三个条件判断逻辑到这里,组装$meta_query_args if ( isset( $request['course_type'] ) && $request['course_type'] !== null ) { $meta_query_args[] = array( 'key' => 'course_type', 'value' => $request['course_type'], 'compare' => '=' ); } // course_no、course_cycles的判断逻辑同理添加在这里 if ( count( $meta_query_args ) > 1 ) { $query->set( 'meta_query', $meta_query_args ); } } }, 999 );
内容的提问来源于stack exchange,提问作者Felix G.
相关产品推荐
相关产品推荐

