一,背景:
1,用 PHP 写 API 时,通过 POST 方式来进行交互 json 数据
2,常用的接收 POST 数据使用 PHP 的全局变量 $_POST
二,问题:
1,API 写好后,发现有人调用成功,有人失败,见鬼了
2,查看日志,发现调用失败的要不是 POST 数据为空,要不就是数据格式异常
3,一开始以为他们调用接口的代码有问题,程序员都会觉得自己代码没问题,事实证明一般都是自己问题
三,解释:
1,经过网上查询,发现是 PHP 接收 POST 数据的代码有问题
全局变量 $_POST 接收 POST 数据是有条件的
官网已经写得非常清楚
An associative array of variables passed to the current script via the HTTP POST method when using application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type in the request.
翻译过就是
$_POST 接收的参数条件, HTTP 请求头 Content-Type 必须是 application/x-www-form-urlencoded 或者 multipart/form-data
2,一般的 web 网页表单 form 提交,符合以上的请求头要求,但是这次的 API 交互数据格式是 json ,部分调用 API 的请求头设置为 Content-Type: application/json ,所以 $_POST 接收不到数据
3,知道原因那就好办了,在接收 POST 参数时做个兼容性处理,通过 php://input 获取请求头为 Content-Type: application/json 的参数
关于 php://input ,官网也有解释
php://input is a read-only stream that allows you to read raw data from the request body. In the case of POST requests, it is preferable to use php://input instead of $HTTP_RAW_POST_DATA as it does not depend on special php.ini directives. Moreover, for those cases where $HTTP_RAW_POST_DATA is not populated by default, it is a potentially less memory intensive alternative to activating always_populate_raw_post_data. php://input is not available with enctype="multipart/form-data".
简单翻译下,除了请求头 enctype(Content-Type) 是 multipart/form-data 之外,php://input 都能接收到请求 request body 中参数,而 POST 方式会把参数放在 request body 中,GET 方式是放在 url 的
4,接手 POST 参数的兼容性代码如下
$header_content_type=$header['Content-Type']; $form_header_type = array('multipart/form-data','application/x-www-form-urlencoded'); if(in_array($header_content_type,$form_header_type)){ $post_data = $_POST; }else{ $post_data = file_get_contents('php://input'); }
Leave a Reply