WordPress的REST API为我们供应了丰富的可扩展功能,现在WP自带的古腾堡编辑器(Gutenberg Editor)则是完备基于Rest API实现的。关于WordPress的更多专题,可以在小程序“软件开拓记”中查看:
(此处已添加小程序,请到今日头条客户端查看)我们通过API供应的posts接口,可以通过参数tags和categories过滤文章列表,前者根据标签ID过滤,后者根据分类ID过滤,多个标签或分类ID,可以利用逗号分割,例如:
Plain Texthttp://www.abot.cn/wp-json/wp/v2/posts?tags=162http://www.tseo.cn/wp-json/wp/v2/posts?tags=41&_embedhttp://www.tseo.cn/wp-json/wp/v2/posts?tags=41,67http://www.tseo.cn/wp-json/wp/v2/posts?tags=41&categories=1

但是最近创造通过标签ID和分类ID获取文章列表的过滤功能失落效了,详细表现为,基于www.tseo.cn开拓的APP和小程序“软件开拓记”中,点击标签和分类,都显示相同的文章,而在网站上直接点击,则没有这个问题。
以是基本可以定位问题出在REST API中,当时利用的版本是WP 6.1.1,升级为WordPress 6.2问题依旧,换到其他几个WP搭建的站群中,却没有创造这个问题。问了几轮chatGPT,给出了几种可能,但是依然不办理问题。
考试测验禁用所有的WordPress插件,问题依旧。网上关于这方面的问题的解答也不多,于是想着是否是自己项目代码的问题了,比如是否重写了REST API中关于posts的函数,或者hook了其他函数导致这项根据tag过滤文章列表的功能失落效?于是开始在代码中搜索“register_rest_route”,遍历了我们项目中的核心WP插件,如下图所示:
逐个排查函数,没有创造问题。
但是无意中看到一篇帖子《WordPress Rest API: filter Posts using a tax_query》,理解了过滤posts的紧张参数是tax_query,紧张代码如下,实在还是通过添加钩子(hook)的办法实现的。
PHPfunction rest_filter_by_custom_taxonomy( $args, $request ) {if ( isset($request['country_slug']) ){$country_slug = sanitize_text_field($request['country_slug']);$args['tax_query'] = [['taxonomy' => 'country','field' => 'slug','terms' => $country_slug,]];}return $args;}add_filter('rest_post_query', 'rest_filter_by_custom_taxonomy', 10, 3);
以上代码紧张hook的工具为“rest_post_query”,于是想是否有用过这个呢?再次搜索代码“rest_post_query”,果真创造有一个地方利用了,代码如下:
PHP //在rest api 过滤 隐蔽分类 的文章列表 function query_book_by_year($args, $request) {if(isset($request["year"]) && intval($request["year"]) > 1500) {$args['meta_key'] = 'year';$args['meta_value'] = intval($request["year"]);}//$args['categories_exclude'] = array('68');abot_wp_log('rest_post_query $args ===>>> '.print_r($args, true));$pre_tax_query = array();//$categories = explode( ',', '68,80' ); // NOTE: Assumes comma(半角逗号) separated taxonomies$categories = explode( ',', zm_get_option('filter_category_in_page_ids') );array_push( $pre_tax_query, array('taxonomy' => 'category','field' => 'term_id','terms' => $categories ,'operator' => 'NOT IN'));//var_dump($pre_tax_query);$tax_query = array('relation' => 'AND',$pre_tax_query);$args[ 'tax_query' ] = $tax_query; abot_wp_log('rest_post_query $args ===>>> '.print_r($args, true));//var_dump($args);exit;return $args;}add_filter('rest_post_query', 'query_book_by_year', 10, 2);
通过利用函数abot_wp_log写日志记录比较,创造以上代码的问题涌现第33行,即“$args[ 'tax_query' ] = $tax_query; ”,由于这里直接将tax_query参数重新赋值了,如果这之前参数tax_query有值,则丢失;而我们通过网址要求REST API的时候带的参数tags和categories正式在这个参数中。以是须要将33行代码修正为:
PHP if(!$args[ 'tax_query' ]){$args[ 'tax_query' ] = $tax_query;}else{$args[ 'tax_query' ] = array_merge($args[ 'tax_query' ], $tax_query);}
修复此BUG后,完全的tax_query的值的示例日志如下,重点看tax_query的部分,于是问题办理。
rest_post_query $args ===>>> Array( [author__in] => Array ( ) [author__not_in] => Array ( ) [post__not_in] => Array ( ) [post__in] => Array ( ) [order] => desc [orderby] => date [paged] => 1 [search_columns] => Array ( ) [post_status] => Array ( [0] => publish ) [date_query] => Array ( ) [posts_per_page] => 10 [tax_query] => Array ( [0] => Array ( [taxonomy] => post_tag [field] => term_id [terms] => Array ( [0] => 41 ) [include_children] => [operator] => IN ) [relation] => AND [1] => Array ( [0] => Array ( [taxonomy] => category [field] => term_id [terms] => Array ( [0] => 68 ) [operator] => NOT IN ) ) ) [post_type] => post)