http://blog.163.com/miracle_tan/blog/static/1632471052010330101950236/
这几天,为了php创建一个“可以轻松理解”的WSDL文件而折腾了一会,实话说,php在这方面还是一个SB,即使最新的版本,还是令我比较失望的。但,我还是有解决方案的。
Tags:php wsdl SOAP WebService
来,先搞个demo上来瞧瞧。创建一个WebService层比较简单:
<?php
class TestWebServices2 {
function GetGUIDNode($GUID1,$GUID2){
Return '$GUID1='.$GUID1.',and $GUID2='.$GUID2;
}
}
ini_set("soap.wsdl_cache_enabled", "0"); //禁止wsdl缓存
$server = new SoapServer('server3.wsdl',array('uri'=>'urn:TestWebServices2'));
$server->setClass("TestWebServices2");
$server->handle();
?>
这个服务层的wsdl文件我们暂时不说,当作已经存在了,再看客户端代码:
<?php
header("Content-Type: text/html; charset=utf-8");
$ws = "http://s/test/oksoap/server3.php?wsdl";
$client = new SoapClient($ws,array('trace' => 1,'uri'=>'urn:TestWebServices2'));
echo("SOAP服务器提供的开放函数:");
echo('<pre>');
var_dump($client->__getFunctions());
echo('</pre>');
echo("SOAP服务器提供的Type:");
echo('<pre>');
var_dump($client->__getTypes());
echo('</pre>');
echo("执行GetGUIDNode的结果:");
try {
$username = $client->GetGUIDNode('5do8','para 2');
} catch (SoapFault $fault){
echo "Fault! co de:",$fault->faultcode,", string: ",$fault->faultstring;
}
echo(htmlspecialchars($client->__getLastRequest()));
echo('<hr>');
echo(htmlspecialchars($client->__getLastResponse()));
echo('<hr>');
echo('<hr>');
var_dump($username);
?>
header("Content-Type: text/html; charset=utf-8");
$ws = "http://s/test/oksoap/server3.php?wsdl";
$client = new SoapClient($ws,array('trace' => 1,'uri'=>'urn:TestWebServices2'));
echo("SOAP服务器提供的开放函数:");
echo('<pre>');
var_dump($client->__getFunctions());
echo('</pre>');
echo("SOAP服务器提供的Type:");
echo('<pre>');
var_dump($client->__getTypes());
echo('</pre>');
echo("执行GetGUIDNode的结果:");
try {
$username = $client->GetGUIDNode('5do8','para 2');
} catch (SoapFault $fault){
echo "Fault! co
}
echo(htmlspecialchars($client->__getLastRequest()));
echo('<hr>');
echo(htmlspecialchars($client->__getLastResponse()));
echo('<hr>');
echo('<hr>');
var_dump($username);
?>
OK,然后着手WSDL部分的说明,首先,我这里说的是WSDL1.1,烂!不很严格主要是。
很多网上的SB说可以用ZEND创建一个wsdl就完事了,这种同学可能在php5.2.x这种最强版本(^-^)下还没测试过或者没有仔细的看php服务端的返回值,很负责任的说,empty,对了,生成的WDSL最好若经过M$的WSDL根据的验证。。。就OK了。
ZEND创建的 WSDL没错,错在php的SoapServer无法识别一个最正常的WSDL文件,shit!问题就在namespace下面。
我先说说一个正常的WSDL的几个部分:
1: wsdl:types 类型,指明W3C的XMLSchema下面不识别的。
2:wsdl:message 消息,传递的信号。
3:wsdl:portType 指明匹配消息与执行的方法
4:wsdl:binding 真正绑定执行服务器方法与客户端方法
5:wsdl:service 公开的WebService名称
这五大部分的关系就是逐步加深,一个迂回。
我这里只说wsdl:types和wsdl:message在php解析中的问题,首先看:
<wsdl:message name="GetGUIDNodeRequest">
<wsdl:part name="GUID1" type="xsd:string" />
<wsdl:part name="GUID2" type="xsd:string" />
</wsdl:message>
<wsdl:message name="GetGUIDNodeResponse">
<wsdl:part name="GetGUIDNodeResult" type="xsd:string" />
</wsdl:message>
这是一个请求的消息,一个message封装了part部分的参数,其中part有三个重要属性,name就是名称,type就是类型,还有个element,就是wsdl:types所定义的TYPE! 问题就在这里,PHP目前还无法正确识别element所定义的类型。
so...
解决方案:
1:找出WSDL文件,保证
<wsdl:types>
<xsd:schema elementFormDefault="qualified" targetNamespace="[你的NAMASPACE]">
</xsd:schema>
</wsdl:types>
<xsd:schema elementFormDefault="qualified" targetNamespace="[你的NAMASPACE]">
</xsd:schema>
</wsdl:types>
2:找到wsdl:message这个,其中的wsdl:part的element属性全部换成type指明的,type="xsd:string"这种。
然后可以通过微软wsdl的验证。
补充:这样php的__getTypes将是array(0),这个关系不大。