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. }


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值