php://input、$_POST 和 $HTTP_RAW_POST_DATA 的区别与详解

烂漫一生 提交于 2019-11-27 17:06:38

        PHP 用于开发 webservice 的 API 接口与客户端做数据交互时不一定会使用 PHP 可以处理的数据格式进行通信,比如 API 常用的 json xml,在此场景下我们需要使用其他的方式获取客户端发来的数据然后进行处理,下面我们就实例模拟下客户端请求 PHP API 场景下的数据交互方式。

        同时要理解 get 请求并未携带表单数据,get 请求的本质是请求服务器的某一资源,其向服务器发送的数据都位于请求头的 Query String/Query Path 中,请求头是 uri,注意理解 get 请求的语意,是去服务器获取资源而不是向服务器发送“数据”。 post 请求则是载有 Form Data 即表单数据的, 是想服务器发送 “数据” 的

    get                                                                               post

        

    可以看出get的参数都是附在请求头中,并不像post中有content-length /content-type /from data 这些描述请求携带的数据内容的属性值

php支持的数据类型

PHP 支持的数据格式(注意:这里说的支持不是指简单的获取到,意为可以进行自动处理,自动填充到 $_POST/ $_FILES中去,再次强调,get 请求并没有向服务器发送“数据”,它是取,不是存,所以 $_GET 的是参数而不是数据)

    application/x-www-form-urlencoded 普通的表单数据

    multipart/form-data 上传文件的表单 enctype="multipart/form-data"

PHP 不支持的数据格式

     application/json

     application/xml


不能处理但可以获取到,你可以自己手动处理,参照表



application/x-www-form-urlencoded multipart/form-data  application/json application/xml
php://input 可获取 不可获取 可获取 可获取
$_POST 可获取 可获取 不可获取 不可获取
$HTTP_RAW_POST_DATA 可获取 不可获取 可获取 可获取


PS: $HTTP_RAW_POST_DATA 已经被 PHP7 废弃,原因是 php://input 完全囊括了它的所有功能,且其对服务器的压力要比 php://input 大很多,最懦弱的是它默认配置下是让位 $_POST 的,如果 $_POST 能处理数据的话他就得靠边站,当然你可以配置 php.ini 将 always_populate_raw_post_data  配置项打开,则会一直填充其所能识别的数据,即便 $_POST 的也能处理。


PHP的数据处理方式

php://input: 除数据类型为 multipart/form-data 的不能识别外,其他格式都可以获取,而后我们可以根据数据类型处理

$_POST: 可以识别 application/x-www-form-urlencoded multipart/form-data 格式,json xml 无法识别

$HTTP_RAW_POST_DATA :识别能力与 php://input 相同,默认配置下与 $_POST 互斥且优先级低于 $_POST


实例

先贴出服务端代码

注意当发送的数据为 multipart/form-data 时 PHP 会将文件类型的数据存放在 $_FILES 中,文本的存放于 $_POST 中,但他们是同一组的,都是 from data 中的数据,与 $_GET 是不同的,$_GET 中填充的是请求头中 Query String 的参数

<?php
/**
 * @author sallency
 * @date 2016-3-4 11:03:23
 * @desc 简单模拟PHP作为API时如何处理各种格式的数据
 */

error_reporting(0);

echo "==== 客户端发送的数据格式 =====" . PHP_EOL;
echo "REQUEST_METHOD: " . $_SERVER['REQUEST_METHOD'] . PHP_EOL;
echo "ACCEPT: " . $_SERVER['HTTP_ACCEPT'] . PHP_EOL;
echo "CONTENT_TYPE: " . ($_SERVER['CONTENT_TYPE'] ? $_SERVER['CONTENT_TYPE'] : "null") . PHP_EOL;

echo PHP_EOL . "===== php://input 数据 ========" . PHP_EOL;
echo file_get_contents('php://input') . PHP_EOL;

echo PHP_EOL . '===== $_POST 数据 =============' . PHP_EOL;
print_r($_POST);

//当 multipart/form-data 类型时文件数据是存放在 $_FILES 中的 文本则 $_POST 中
echo PHP_EOL . '===== $_FILES 数据 =============' . PHP_EOL;
print_r($_FILES);

echo PHP_EOL . '===== $HTTP_RAW_POST_DATA =====' . PHP_EOL;
echo $HTTP_RAW_POST_DATA ? $HTTP_RAW_POST_DATA : 'null' . PHP_EOL;

?>

1、发送 application/x-www-form-urlencoded 标准数据 

    

            可以看出 php://input 和  $_POST/$_FILES 里都能正常识别接收此类型的数据,其实 $_HTTP_RAW_POST_DATA 也能接受,但我们说过默认情况下它和 $_POST/$_FILES 是互斥且优先级低,所以 $_POST/$_FILES 中有数据时它就不会被填充了,可修改配置让他一直填充自己可识别的数据。

2、发送 multipart/form-data

    php://input 和 $HTTP_RAW_POST_DATA 为空,说明它俩无法识别此类行的数据流(其实也只是不能识别此类行的,其他的都没问题),$_POST/$_FILES 则可以正常识别

3、发送 application/json 格式

    

        数据体:   

        

    php://input 和 $HTTP_RAW_POST_DATA 可识别, $_POST 则无法识别

4、发送 application/xml 格式

       

            数据体:

               

            php://input 和 $HTTP_RAW_POST_DATA 可识别, $_POST 则无法识别

总结

        当然还有很多其他的数据类型我们就不做测试了,大家可以自己动手。

        application/x-www-form-urlencoded 是 PHP 的标准数据流类型, 可以被三者识别

        multipart/form-data 只能被 $_POST/$_FILES 识别处理,另外的两者无法识别

        application/json application/xml 等就只能被 php://input 和 $HTTP_RAW_POST_DATA 识别了,这也是我们日常开发接口时往往使用 php://input 数据输入流来获取客户端请求携带的数据

        PS:    除了 POST 动作可携带数据体, PUT/PATCH/OPTIONS/HEAD/DELETE动作也都可以携带数据体,它们不像 POST 动作数据会被自动填充处理, 没有对应的全局变量,这时我们就可以使用 php://input 来获取此类动作所携带的原始数据。

        GET/VIEW 动作不携带数据流所以三者都会是空,但 $_GET 会被填充

                    PHP 的 $_POST 中只会填充数据格式OK的 POST 动作的数据, 但 POST/PUT/PATCH/DELETE/OPTION 在数据格式符合的前提下请求会填充到 php://input 中,$HTTP_RAW_POST_DATA 则无法响应 PUT/PATCH/DELETE/OPTION 动作的数据,例如:

          PUT 请求

        

            PATCH 请求

          

                 DELETE请求

          

                OPTIONS 请求

           

                HEAD 请求则返回响应头信息

           

            

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!