PHP 使用 file_get_contents 接收 POST 的資料

一般接收 POST 资料都是使用 $_POST 这个变量,

但 $_POST 只能取得 Content-type 為 application/x-www-form-urlencoded 或 multipart/form-data 的資料。
當 Content-type 為 text/xml 等其他類型的資料,$_POST便無法取得。

若有接收其他類型 Content-type 的需求,可以使用 php://input,
php://input 可以讀取 request body 的資料,所以可以取得 HTTP POST 的資料,
但有一個限制,就是當 Content-type 為 multipart/form-data ,php://input 會取得空值,無法使用。

下面範例 php://input 搭配 file_get_contents 使用,和 $_POST 比較在 Content-type 分別為 multipart/form-data、application/x-www-form-urlencoded、text/xml 時,兩者接收資料的情況

接收資料的程式:
後面範例用來 request 的網址:http://127.0.0.1/test/test.php 
1
2
3
$postdata  = file_get_contents ( "php://input" , 'r' );
var_dump( $postdata ); // php://input
var_dump( $_POST );

範例 1:(multipart/form-data )
使用 curl 模擬 HTTP POST,Content-type 為 multipart/form-data
(CURLOPT_POSTFIELDS 資料為陣列時,會以 multipart/form-data 方式傳送)
1
2
3
4
5
6
7
8
$ch  = curl_init();
$data  = array ( 'aa' => '123' , 'bb' => '456' );
curl_setopt( $ch , CURLOPT_URL, 'http://127.0.0.1/test/test.php' );
curl_setopt( $ch , CURLOPT_POST, 1);
curl_setopt( $ch , CURLOPT_POSTFIELDS, $data );
curl_setopt( $ch , CURLOPT_HEADER,0);
curl_exec( $ch );
curl_close( $ch );
輸出結果:file_get_contents("php://input",'r') 取不到 multipart/form-data 的值
$postdata:string(0) ""
$_POST (OK):array(2) { ["aa"]=> string(3) "123" ["bb"]=> string(3) "456" } 

範例 2:(application/x-www-form-urlencoded )
使用 curl 模擬 HTTP POST,Content-type 為 application/x-www-form-urlencoded
1
2
3
4
5
6
7
8
9
$ch  = curl_init();
$data  = 'aa=123&bb=456' ;
curl_setopt( $ch , CURLOPT_URL, 'http://127.0.0.1/test/test.php' );
curl_setopt( $ch , CURLOPT_HTTPHEADER, array ( "Content-type: application/x-www-form-urlencoded" ));
curl_setopt( $ch , CURLOPT_POST, 1);
curl_setopt( $ch , CURLOPT_POSTFIELDS, $data );
curl_setopt( $ch , CURLOPT_HEADER,0);
curl_exec( $ch );
curl_close( $ch );
輸出結果:file_get_contents("php://input",'r') 和 $_POST 的資料一樣,但 $_POST 已轉成陣列
$postdata (OK):string(13) "aa=123&bb=456"
$_POST (OK):array(2) { ["aa"]=> string(3) "123" ["bb"]=> string(3) "456" }

範例 3:(text/xml )
使用 curl 模擬 HTTP POST,Content-type 為 text/xml
1
2
3
4
5
6
7
8
9
$ch  = curl_init();
$data  = '<?xml version="1.0" encoding="utf-8"?><root><aa>123</aa><bb>456</bb></root>' ;
curl_setopt( $ch , CURLOPT_URL, 'http://127.0.0.1/test/test.php' );
curl_setopt( $ch , CURLOPT_HTTPHEADER, array ( "Content-type: text/xml;charset=\"utf-8\"" ));
curl_setopt( $ch , CURLOPT_POST, 1);
curl_setopt( $ch , CURLOPT_POSTFIELDS, $data );
curl_setopt( $ch , CURLOPT_HEADER,0);
curl_exec( $ch );
curl_close( $ch );
輸出結果:file_get_contents("php://input",'r') 可以讀取 POST 過來的 XML 資料,$_POST 無法讀取
$postdata (OK):string(36) "<?xml version="1.0" encoding="utf-8"?><root><aa>123</aa><bb>456</bb></root>"
$_POST:array(0) {}

結論: 
所以如果有一 PHP 程式,用來接收其它地方 POST 過來的資料,例如是 XML 的資料,應該就可以利用 file_get_contents("php://input",'r') 來取得 POST 過來的內容。

PHP将XML转换成数组
做接口开发的时候经常会碰到别人提交给你的是xml格式的数据,常见的微信接口、支付宝接口等,他们的接口如发送消息通信都是xml格式的,那么我们先想办法拿到这个xml数据,然后再将其转化成数组。

假设我们获取到一个这样的XML:

<root>
    <user>月光光abcd</user>
    <pvs>13002</pvs>
    <ips>
        <baidu_ip>1200</baidu_ip>
        <google_ip>1829</google_ip>
    </ips>
    <date>2016-06-01</date>
</root>
通过simplexml_load_string()解析读取xml数据,然后先转成json格式,再转换成数组。
function xmlToArray($xml){
//禁止引用外部xml实体
libxml_disable_entity_loader(true);
$xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
$val = json_decode(json_encode($xmlstring),true);
return $val;
}

也可以

调用xmlToArray()可得到以下结果:


得到数组后,我们就可以对数据进行各种处理了。



语法

PHP的语法simplexml_load_string()函数具有以下语法。

simplexml_load_string(data,classname,options,ns,is_prefix);

 

参数

参数 是必须的 描述
数据 需要。 一个格式正确的XML字符串
班级名称 可选的。 新对象的类
选项 可选的。 额外的Libxml参数。通过指定选项和1或0(TRUE或FALSE,例如LIBXML_NOBLANKS(1))来设置
ns 可选的。 命名空间前缀或URI
is_prefix 可选的。 如果ns是前缀,则为TRUE。如果ns是URI,则为FALSE。默认值为FALSE

选项的可能值:

  • LIBXML_COMPACT - 激活节点分配优化(可加速应用程序)
  • LIBXML_DTDATTR - 设置默认DTD属性
  • LIBXML_DTDLOAD - 加载外部子集
  • LIBXML_DTDVALID - 使用DTD进行验证
  • LIBXML_NOBLANKS - 删除空白节点
  • LIBXML_NOCDATA - 将CDATA合并为文本节点
  • LIBXML_NOEMPTYTAG - 展开空标记(例如对<br> </ br>),仅在DOMDocument-> save()和DOMDocument-> saveXML()函数中可用
  • LIBXML_NOENT - 替代实体
  • LIBXML_NOERROR - 不显示错误报告
  • LIBXML_NONET - 加载文档时禁用网络访问
  • LIBXML_NOWARNING - 不显示警告报告
  • LIBXML_NOXMLDECL - 保存文档时删除XML声明
  • LIBXML_NSCLEAN - 删除多余的命名空间声明
  • LIBXML_PARSEHUGE - 设置XML_PARSE_HUGE标志,放宽解析器的任何硬编码限制。这会影响极限,如文档的最大深度和文本节点大小的限制
  • LIBXML_XINCLUDE - 实现XInclude替换
  • LIBXML_ERR_ERROR - 获取可恢复的错误
  • LIBXML_ERR_FATAL - 获取致命错误
  • LIBXML_ERR_NONE - 获取无错误
  • LIBXML_ERR_WARNING - 获取简单的警告
  • LIBXML_VERSION - 获取libxml版本
  • LIBXML_DOTTED_VERSION - 获取点分的libxml版本

 

返回值

成功时返回SimpleXMLElement对象。失败时为FALSE。

 

实例1

将格式良好的XML字符串转换为SimpleXMLElement对象,然后输出该对象的键和元素:

<?php
//  http://www.manongjc.com/article/1630.html
$note=<<<XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<book>
    <name>PHP</name>
    <name>Java</name>
</book>
XML;

$xml=simplexml_load_string($note);
print_r($xml);
?>

上面的代码生成以下结果。

SimpleXMLElement Object
(
    [name] => Array
        (
            [0] => PHP
            [1] => Java
        )

)

 

实例2

输出XML字符串中每个元素的数据:

<?php
//  http://www.manongjc.com/article/1630.html
$note=<<<XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<book>
    <name>PHP</name>
    <name>Java</name>
</book>
XML;

$xml=simplexml_load_string($note);
echo $xml->to . "\n";
echo $xml->from . "\n";
echo $xml->heading . "\n";
echo $xml->body;
?>

 

实例3

在XML字符串中为每个子节点输出元素的名称和数据:

<?php
//  http://www.manongjc.com/article/1630.html
$note=<<<XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<book>
    <name>PHP</name>
    <name>Java</name>
</book>
XML;

$xml=simplexml_load_string($note);
echo $xml->getName() . "\n";

foreach($xml->children() as $child){
   echo $child->getName() . ": " . $child . "\n";
}
?>

上面的代码生成以下结果。

book
name: PHP
name: Java



对象转成数组:

可以直接array()来转,但是有些情况不适用,数据结构会变。(未验证)

  1. 1.
  2. //PHP stdClass Object转array  
  3. function object_array($array) {  
  4.     if(is_object($array)) {  
  5.         $array = (array)$array;  
  6.     } 
  7.     if(is_array($array)) {
  8.         foreach($array as $key=>$value) {  
  9.             $array[$key] = object_array($value);  
  10.         }  
  11.     }  
  12.     return $array;  
  13. }
  14. 2.
  15. $array = json_decode(json_encode(simplexml_load_string($xmlString)),TRUE);
  16. 3.
  17. function object2array_pre(&$object) {
  18.     if (is_object($object)) {
  19.         $arr = (array)($object);
  20.     } else {
  21.         $arr = &$object;
  22.     }
  23.     if (is_array($arr)) {
  24.         foreach($arr as $varName => $varValue){
  25.             $arr[$varName] = $this->object2array($varValue);
  26.         }
  27.     }
  28.     return $arr;
  29. }
  30. 4.如果是10W的数据量的话,执行要进1s,结构再复杂些,可以达到3s,性能太差了,可以用以下替换:
  31. function object2array(&$object) {
  32.     $object =  json_decode( json_encode( $object),true);
  33.     return  $object;
  34. }


猜你喜欢

转载自blog.csdn.net/qq_34642668/article/details/80674351
今日推荐