1. 问题重现
<?php
$client = new \SoapClient('http://192.168.0.111:8989/dbservice/selectAll?wsdl');
$param = [];
$param['users'] = 'all';
$result = $client->selectAllinspectOperation($param);
var_dump($result);
?>
运行后的返回结果如下,以下结果是全部返回内容,并没有隐藏什么:
object(stdClass)[2]
public 'record' =>
array (size=2)
0 =>
object(stdClass)[3]
1 =>
object(stdClass)[4]
2. 思考过程
- 首先,运行结果没有报错。
- 然后,
selectAllinspectOperation()
这个函数的目的是返回数据库中所有的结果。而数据库中目前只有两条数据,所以从返回结果来看,正好有个长度为2的数组。所以我认为查询是成功,且返回了正确的条目数。 - object(stdClass)这个东东我比较陌生,查了下php文档,是个叫做基类的对象。具体是啥东东对本问题不是很重要,就不赘述了。当时我认为问题就是在object(stdClass)上,可能object(stdClass)把返回结果都封装隐藏起来了,所以看不到。
- 于是乎又是一顿狂查,网上查到了一个函数get_object_vars()可以把object转为数组,试了一下,确实是把对象转为数组了,上面代码最后一句修改以下,运行结果如下:
//var_dump(get_object_vars($result));运行结果 array (size=1) 'record' => array (size=2) 0 => object(stdClass)[3] 1 => object(stdClass)[4]
不过上面的结果只把最外层的object转为了数组,于是再深入以下,把里面的object(stdClass)也转为数组,同样是最后一行代码修改下,运行结果如下:
//var_dump(get_object_vars(get_object_vars($result)["record"][0]));运行结果 array (size=0) empty
- 这下子又晕了,得到的是空值。于是又是一顿狂查,查到了几个SoapClient中的函数,可以打印SoapClient调用过程中的各种信息,于是把每个函数都写下来看看能返回什么结果:
echo("打印暴露的方法:"); var_dump($client->__getFunctions()); print("<br/>"); echo("打印对应方法的参数和参数类型:"); var_dump($client->__getTypes()); print("<br/>"); echo("最后一次请求的头数据:"); var_dump($client->__getLastRequestHeaders()); echo "<br>"; echo("最后一次请求的数据:"); var_dump($client->__getLastRequest()); echo "<br>"; echo("最后一次返回的头数据:"); var_dump($client->__getLastResponseHeaders()); echo "<br>"; echo("最后一次返回的数据:"); var_dump($client->__getLastResponse());
最重要的就是最后一个
__getLastResponse()
函数,发现所有期望的查询结果实际都返回回来了:
- 这就奇怪了不是吗?明明已经返回了查询结果,为什么之前获取不到呢?于是我放弃了这个接口,而是测试接口文档中其它的接口,却惊喜的发现其它接口是可以正常返回数据的,虽然返回的也是
object(stdClass)
类型数据,但是object(stdClass)
下面是有具体的数值的。于是我开始怀疑,是不是给的接口有问题? - 于是又是一轮查询和思考。说实话,这方面的文档真的很少。经过国内、国外各种网站的查询和信息汇总。最终确定,确实是接口有问题。
3. 问题说明。
基本可以肯定的是,如果可以通过__getLastResponse()
看到数据,而打印的数据是空object(stdClass)
,这个不是使用WebService的问题,而是服务器端WebService的返回值不符合相关规范,导致SoapClient无法对返回结果正常解析导致的。
所以,不要再症结这个问题了,除非你能修改WebService的内容,否则常规手段解决不了这个问题。
4. 解决方案。
之前也说过了,可以通过__getLastResponse()
获取返回的内容。反正已经有了结果了,直接处理结果字符串不就好了吗。
所以解决方案很简单,直接使用PHP的XML处理函数,或者直接写个正则表达式获取里面的结果就好了!
5. 总结
我把以上这些情况反馈给了接口提供方,那边也最终证实,确实是他们返回的数据格式有瑕疵。
重要的事情说三遍,遇到这种情况:
不是你的问题!
不是你的问题!
不是你的问题!
是WebService的问题!
是WebService的问题!
是WebService的问题!