You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法捕获引发PHP错误的WooCommerce REST API请求,求解决方法

捕获引发WooCommerce REST API内部PHP错误的完整请求内容

问题背景

第三方应用通过WooCommerce REST API插入商品数据,但该应用不记录出站请求。此请求触发了PHP致命错误,错误日志如下:

[16-Jan-2023 14:52:23 UTC] PHP Fatal error:  Uncaught TypeError: preg_match(): Argument #2 ($subject) must be of type string, WP_REST_Request given in /home/CENSORED/public_html/wp-includes/formatting.php:1596
Stack trace:
#0 /home/CENSORED/public_html/wp-includes/formatting.php(1596): preg_match('/[\\x80-\\xff]/', Object(WP_REST_Request))
#1 /home/CENSORED/public_html/wp-includes/formatting.php(2207): remove_accents(Object(WP_REST_Request))
#2 /home/CENSORED/public_html/wp-includes/class-wp-hook.php(310): sanitize_title(Object(WP_REST_Request))
#3 /home/CENSORED/public_html/wp-includes/plugin.php(205): WP_Hook->apply_filters(Object(WP_REST_Request), Array)
#4 /home/CENSORED/public_html/wp-includes/taxonomy.php(1751): apply_filters('pre_term_slug', Object(WP_REST_Request), 'pa_colour')
#5 /home/CENSORED/public_html/wp-includes/taxonomy.php(1653): sanitize_term_field('slug', Object(WP_REST_Request), 0, 'pa_colour', 'db')
#6 /home/CENSORED/public_html/wp-includes/taxonomy.php(2385): sanitize_term(Array, 'pa_colour', 'db')
#7 /home/CENSORED/public_html/wp-content/plugins/woocommerce/includes/rest-api/Controllers/Version3/class-wc-rest-terms-controller.php(407): wp_insert_term('DENIM BLUE', 'pa_colour', Array)
#8 /home/CENSORED/public_html/wp-includes/rest-api/class-wp-rest-server.php(1171): WC_REST_Terms_Controller->create_item(Object(WP_REST_Request))
#9 /home/CENSORED/public_html/wp-includes/rest-api/class-wp-rest-server.php(1018): WP_REST_Server->respond_to_request(Object(WP_REST_Request), '/wc/v2/products...', Array, NULL)
#10 /home/CENSORED/public_html/wp-includes/rest-api/class-wp-rest-server.php(442): WP_REST_Server->dispatch(Object(WP_REST_Request))
#11 /home/CENSORED/public_html/wp-includes/rest-api.php(410): WP_REST_Server->serve_request('/wc/v2/products...')
#12 /home/CENSORED/public_html/wp-includes/class-wp-hook.php(308): rest_api_loaded(Object(WP))
#13 /home/CENSORED/public_html/wp-includes/class-wp-hook.php(332): WP_Hook->apply_filters(NULL, Array)
#14 /home/CENSORED/public_html/wp-includes/plugin.php(565): WP_Hook->do_action(Array)
#15 /home/CENSORED/public_html/wp-includes/class-wp.php(399): do_action_ref_array('parse_request', Array)
#16 /home/CENSORED/public_html/wp-includes/class-wp.php(780): WP->parse_request('')
#17 /home/CENSORED/public_html/wp-includes/functions.php(1332): WP->main('')
#18 /home/CENSORED/public_html/wp-blog-header.php(16): wp()
#19 /home/CENSORED/public_html/index.php(17): require('/home/CENSORED...')
#20 {main}
thrown in /home/CENSORED/public_html/wp-includes/formatting.php on line 1596

测试环境为全新最新版WordPress+WooCommerce,仅安装日志类插件,无其他第三方插件。已尝试以下方法但未捕获到目标请求:

  • 查看Apache访问日志,无请求体内容
  • 使用WP REST API Log插件,仅记录有效请求,遗漏触发错误的请求
  • 使用Log HTTP Requests插件,未捕获到REST API请求
  • 自定义代码记录请求,仅无效请求能写入error_log,触发致命错误的请求无记录,推测请求语法合法,错误为内部PHP Bug

解决方案

方法1:通过WordPress钩子提前记录请求

在当前主题的functions.php中添加以下代码,会在REST API处理逻辑启动前,将完整请求信息写入PHP error_log:

add_action( 'rest_api_init', function() {
    $request = WP_REST_Request::from_global();
    $log_entry = sprintf(
        "[%s] REST API Request:\nMethod: %s\nURL: %s\nHeaders: %s\nBody: %s\nParams: %s\n",
        current_time( 'mysql' ),
        $request->get_method(),
        $request->get_url(),
        print_r( $request->get_headers(), true ),
        $request->get_body(),
        print_r( $request->get_params(), true )
    );
    error_log( $log_entry );
}, 1 ); // 设置最高优先级,确保在错误触发前执行

触发错误后,查看服务器的PHP error_log即可找到对应的完整请求数据。

方法2:修改PHP配置记录原始请求

编辑服务器的php.ini文件,添加或修改以下配置:

log_errors = On
error_log = /var/log/php/error.log ; 替换为实际的日志路径
always_populate_raw_post_data = On

重启Apache或Nginx服务后,PHP会记录所有入站请求的原始数据,包括触发错误的请求内容。

方法3:服务器级日志配置捕获请求体

Apache配置

修改虚拟主机配置文件,添加自定义日志格式:

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{Content-Type}i\" \"%POST_DATA\"" combined_with_body
CustomLog /var/log/apache2/access.log combined_with_body ; 替换为实际日志路径

重启Apache后,访问日志会包含POST请求的完整内容。

Nginx配置

在Nginx的server块中添加自定义日志格式:

log_format full_request '$remote_addr - $remote_user [$time_local] '
                       '"$request" $status $body_bytes_sent '
                       '"$http_referer" "$http_user_agent" '
                       '"$request_body"';
access_log /var/log/nginx/access.log full_request ; 替换为实际日志路径

重启Nginx后,access.log会记录请求体内容。


内容的提问来源于stack exchange,提问作者Robbie Lewis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 06:30:47