资讯专栏INFORMATION COLUMN

PHP中的$_POST和file_get_content('php://input

LiuZh / 1405人阅读

摘要:核心代码在类中我们会定义几个的数组,通过来进行判断处理,针对性的进行数据获取和转换。

PHP中的$_POST和file_get_content("php://input")

故事背景:又是一个激情四射的故事。前段时间我们在弄我们自己的开源基础组件,基础组件包括我们经常使用的一些组件,比如说aliyunMQ,aliyunSearch、request(基于guzzle)等进行封装处理。就是这个request引发了一些美好的误会。

$_POST

老规矩,查看官方文档,全世界都会骗你,但是文档不会骗你。

$HTTP_POST_VARS [已弃用]
$_POST -- $HTTP_POST_VARS [已弃用] — HTTP POST 变量
当 HTTP POST 请求的 Content-Type 是 application/x-www-form-urlencoded 或 multipart/form-data 时,会将变量以关联数组形式传入当前脚本。

$HTTP_POST_VARS 包含相同的信息,但它不是一个超全局变量。 (注意 $HTTP_POST_VARS 和 $_POST 是不同的变量,PHP 处理它们的方式不同)

一看文档就知道全部信息了,$_POST支持的request中的header中的content-type的类型只有application/x-www-form-urlencoded 或 multipart/form-data 。

当我们使用guzzle的时候它会根据你传入的params是否是数组进行判断,如果不是数组会在body中。但是如果是数组它就会按照json方式进行传递,content-type会application/json的方式当然不会被$_POST进行处理。所以,这边是没有毛病的。但是,难道因为用了这个组件就不进行这个类型处理了吗?显然不行。

php://input
php:// — 访问各个输入/输出流(I/O streams)

PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器。

php://input 是个可以访问请求的原始数据的只读流。 POST 请求的情况下,最好使用 php://input 来代替 $HTTP_RAW_POST_DATA,因为它不依赖于特定的 php.ini 指令。 而且,这样的情况下 $HTTP_RAW_POST_DATA 默认没有填充, 比激活 always_populate_raw_post_data 潜在需要更少的内存。 enctype="multipart/form-data" 的时候 php://input 是无效的。

Note: 在 PHP 5.6 之前 php://input 打开的数据流只能读取一次; 数据流不支持 seek 操作。 不过,依赖于 SAPI 的实现,请求体数据被保存的时候, 它可以打开另一个 php://input 数据流并重新读取。 通常情况下,这种情况只是针对 POST 请求,而不是其他请求方式,比如 PUT 或者 PROPFIND。

这个东西说实话,就是$_POST基于这个进行封装处理了一层。它能够获取到最原始的数据,不管你是什么content-type,它都能够获取到数据。所以,当我们的post的过来的数据是原始数据的时候,比如说是application/json或者" application/x-json,text/xml, application/xml,application/x-xml这些时候,$_POST都是无法获取到数据的。此刻,我们就需要通过php://input进行获取原始数据了。但是,原始数据并不是我们想要的最终格式。因此,我们需要进行封装一层。

parseRequest

request类其实是很好写的,但是一般的类中对post方式传递参数还是老方式。因此,我改写了一般的类中获取post的参数,对于所有post请求方式的方法,针对不同的content-type进行数据获取和原始数据的解析,弄成我们想要的最终数组。
核心代码:

public static function post($key = NULL, $default = NULL)
    {
        $data = [];       if(in_array($_SERVER["CONTENT_TYPE"],self::$formats["json"])){
            $data = file_get_contents("php://input");
            $data = json_decode($data,true);
        }

        if(in_array($_SERVER["CONTENT_TYPE"],self::$formats["xml"])){
            $data = file_get_contents("php://input");
            $data = DataParser::toArray($data);
        }

        if($key==null && !empty($data)){
            return $data;
        }

        if(!empty($data)){
            return isset($data[$key]) ? $data[$key] : $default;
        }

        return static::lookup($_POST, $key, $default);
    }

在类中我们会定义几个conten-type的format数组,通过$_SERVER["CONTENT_TYPE"]来进行判断处理,针对性的进行数据获取和转换。

protected static $formats = array(
        "html" => array("text/html", "application/xhtml+xml"),
        "txt"  => array("text/plain"),
        "js"   => array("application/javascript",
            "application/x-javascript", "text/javascript"),
        "css"  => array("text/css"),
        "json" => array("application/json", "application/x-json"),
        "xml"  => array("text/xml", "application/xml",
            "application/x-xml"),
        "rdf"  => array("application/rdf+xml"),
        "atom" => array("application/atom+xml"),
        "rss"  => array("application/rss+xml"),
    );

针对xml格式的数据,同时封装了数据处理类

public static function toArray($xml)
    {
        if (!$xml) {
            return false;
        }

        // 检查xml是否合法
        $xml_parser = xml_parser_create();
        if (!xml_parse($xml_parser, $xml, true)) {
            xml_parser_free($xml_parser);
            return false;
        }
        libxml_disable_entity_loader(true);

        $data = json_decode(json_encode(simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA)), true);

        return $data;
    }

就是简单的将xml格式数据转换成array数据。

后话

一般$_POST在很多项目中会有使用,基本上用来使用获取参数数据。通常的请求的content-type不会出现很奇怪的,但是我觉得还是需要自己去封装一层进行数据获取的类,能够省去很多麻烦,或者说对于你们项目的一致性有很多帮助。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/25715.html

相关文章

  • PHP其他知识集合

    摘要:引用传递除了对象和资源,其他类型的引用传递都是指向同样的数据,各自互相影响。与基本用法一致,但区别如下没有返回值,有返回值可以输出多个参数,只可以输出一个参数是函数,可以打印复合类型,例如等,主要用于数组打印是函数,把文字格式化以后输出。 命令行执行PHP代码三种方式 1、/usr/local/php/bin/php 后面跟上某个PHP文件 2、/usr/local/php/bi...

    李涛 评论0 收藏0
  • 因为 Java Php 在获取客户端 cookie 方式不同引发的 bug

    摘要:遇到个和在获取客户端方式不同导致跨系统的问题。编码扩展讨论与的区别是什么手册上的解释是返回字符串,此字符串中除了之外的所有非字母数字字符都将被替换成百分号后跟两位十六进制数,空格则编码为加号。 遇到个 Java 和 Php 在获取客户端 cookie 方式不同导致跨系统的问题。所以写了这篇博客梳理下相关知识。 实验 下面通过两个简单的实验,来看Java和Php在获取web请求中的coo...

    legendmohe 评论0 收藏0
  • Swoole 在 Swoft 中的应用

    摘要:在中的应用官网源码解读号外号外欢迎大家我们开发组定了一个就线下聚一次的小目标上一篇源码解读反响还不错不少同学推荐再加一篇讲解一下中使用到的功能帮助大家开启的实战之旅服务器开发涉及到的相关技术领域的知识非常多不日积月累打好基础是很难真正 date: 2017-12-14 21:34:51title: swoole 在 swoft 中的应用 swoft 官网: https://www.sw...

    EscapedDog 评论0 收藏0
  • 说说$POST 、$HTTP_RAW_POST_DATA、php://input三者之间的区别

    摘要:因为在无法识别的时候,就会把数据填入到中。需要设置中的值为才会生效当与可以取到值时为空不能用于中已经移除了这个全局变量,用替代可通过输入流以文件读取方式取得未经处理的原始数据,允许读取的原始数据。和比起来,它给内存带来的压力较小。 $POST $_POST是我们最常用的获取POST数据的方式,它是以关联数组方式组织提交的数据,并对此进行编码处理,如urldecode,甚至编码转换,识别...

    desdik 评论0 收藏0
  • 我的第一个小程序(Discuz! + 微信小程序)

    摘要:微信小程序开发官方文档,正在开发的小程序的源码,都给了我不少启发到小程序上富文本的解析一个优秀的开源项目微信小程序富文本解析组件作用在于解析你论坛上的帖子内容,你论坛上加粗的文字,加了颜色的文字,图片等等,都可以原原本本的展示在小程序中。 关于这个小程序 Github : https://github.com/DowneyL/di...‘ 这个小程序是公司针对一个自家产品的需求,而这个...

    YacaToy 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<