当前位置: 首页 > 后端技术 > PHP

PHP中的$_POST和file_get_content('php---input')

时间:2023-03-29 18:39:31 PHP

$_POST和PHP中的file_get_content('php://input')背景故事:又一个热血故事。前段时间我们在做自己的开源基础组件,其中包括一些我们经常使用的组件,比如aliyunMQ、aliyunSearch、request(基于guzzle)等进行封装。正是这个要求,引起了一些美丽的误会。$_POST的老规矩,查官方文档,全世界都会骗你,文档不会骗你。$HTTP_POST_VARS[deprecated]$_POST--$HTTP_POST_VARS[deprecated]—HTTPPOST变量当HTTPPOST请求的Content-Type为application/x-www-form-urlencoded或multipart/form-data时,变量被传入当前脚本作为关联数组。$HTTP_POST_VARS包含相同的信息,但它不是超全局变量。(注意$HTTP_POST_VARS和$_POST是不同的变量,PHP的处理方式不同。)看文档就知道了。$_POST支持的请求头中content-type的类型只有application/x-www-form-urlencoded或multipart/form-data。我们在使用guzzle的时候,会根据你传入的params是不是数组来判断,如果不是,就会在body中。但是如果是数组,就会以json方式传递,content-type为application/json,当然不会被$_POST处理。所以,这里没有错。但是,是不是因为使用了这个组件,所以没有进行这种处理呢?很明显不是。php://inputphp://—访问各种输入/输出流(I/O流)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无效。注意:在PHP5.6之前,php://input打开的数据流只能读取一次;数据流不支持查找操作。然而,根据SAPI的实现,当请求体数据被保存时,它可以打开另一个php://input数据流并再次读取。通常,这仅适用于POST请求,而不适用于PUT或PROPFIND等其他请求方法。说实话,这个东西是$_POST基于这个封装过程。它能得到最原始的数据,不管你是什么内容类型,它都能得到数据。所以,当我们post出来的数据是原始数据,比如application/json或者'application/x-json,text/xml,application/xml,application/x-xml,$_POST是无法获取到数据的。此时我们需要通过php://input获取原始数据。但是,原始数据并不是我们想要的最终格式。因此,我们需要一层封装。parseRequest类其实写的很好,但是一般类还是老样子给post方法传参。因此,我重写了获取post参数的通用类。所有的post请求方式,都是针对不同的content-type进行数据采集和原始数据分析,最终得到我们想要的数组。核心代码:publicstaticfunctionpost($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)){返回$data;}if(!empty($data)){returnisset($data[$key])?$数据[$键]:$默认值;}returnstatic::lookup($_POST,$key,$default);}在class里面,我们会定义几个content-type的格式数组,使用$_SERVER['CONTENT_TYPE']进行判断和处理,有针对性的进行数据的获取和转换。protectedstatic$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格式的数据,同时封装了数据处理类publicstaticfunctiontoArray($xml){如果(!$xml){返回false;}//检查xml是否合法$xml_parser=xml_parser_create();如果(!xml_parse($xml_parser,$xml,true)){xml_parser_free($xml_parser);返回假;}libxml_disable_entity_loader(true);$data=json_decode(json_encode(simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOCDATA)),true);返回$数据;}就是简单的把xml格式的数据转换成数组数据。一般在很多项目中都会用到$_POST,基本上是用来获取参数数据的。平时request的content-type不会显得很奇怪,但是我觉得还是有必要自己封装一个获取数据的类,这样可以省去很多麻烦,或者对你项目的一致性有很大的帮助。