【发布时间】:2014-08-08 19:56:16
【问题描述】:
我遇到了 PHP SoapClient 的问题。我有以下 WSDL https://api.mindbodyonline.com/0_5/DataService.asmx?WSDL,我正在调用 SelectDataXml。它返回适当的响应,其中包括与 SQL 查询将返回的数据行相对应的对象数组。我已经在 Soap UI 和 __getLastResponse 方法(使用 print_r 例程和 NetBeans 调试器窗口)中检查了响应。我可以将完整的响应视为一个字符串,但该数组是用空的 stdClasses 构建的。我在这里看到了几个答案,建议关闭缓存来解决这个问题。我试过了,但没有。我似乎找不到让它正确构建对象的方法。任何帮助将不胜感激。
已编辑
抽象超类(敏感数据替换为'REMOVED'):
abstract class Mindbody_service {
protected $_userCredentials = array ( "Username" => 'REMOVED', "Password" => 'REMOVED', 'SiteIDs' => array ( 'REMOVED' ) ),
$_sourceCredentials = array ( "SourceName" => 'REMOVED', "Password" => 'REMOVED', 'SiteIDs' => array ( 'REMOVED' ) ),
$_endPoint;
public function __construct( $wsdl, $options = array () )
{
try {
$this->_endPoint = new SoapClient( $wsdl, $options );
} catch ( SoapFault $fault ) {
echo $fault->getMessage();
}
}
}
具体的子类:
include_once ('Mindbody_service.php');
class MindbodyDataServiceResponse {
public $Status,
$ErrorCode,
$XMLDetail,
$ResultCount,
$CurrentPageIndex,
$TotalPageCount,
$Results;
function __construct()
{
$Status = '';
$ErrorCode = 0;
$XMLDetail = '';
$ResultCount = 0;
$CurrentPageIndex = 0;
$TotalPageCount = 0;
$Results = new MindbodyDataServiceResults();
}
}
class MindbodyDataServiceResults {
public $Row;
function __construct()
{
$row = array ();
}
}
class Mindbody_data_service extends Mindbody_service {
private $_query = "Very long SQL command that makes sense to the server";
public function __construct()
{
$wsdl = 'https://api.mindbodyonline.com/0_5/DataService.asmx?wsdl';
$options = array ();
$classMap = array ( 'SelectDataXmlResult' => 'MindbodyDataServiceResponse' );
$options [ 'trace' ] = TRUE;
$options [ 'cache_wsdl' ] = WSDL_CACHE_NONE;
$options [ 'compression' ] = SOAP_COMPRESSION_ACCEPT | SOAP _COMPRESSION_GZIP;
$options [ 'classmap' ] = $classMap;
parent::__construct( $wsdl, $options );
}
public function getSomething( $since = null )
{
$request = array ( 'SourceCredentials' => $this->_sourceCredentials );
$request [ 'SourceCredentials' ] = $this->_sourceCredentials;
$request [ 'UserCredentials' ] = $this->_userCredentials;
$request [ 'XMLDetail' ] = 'Full';
$request [ 'PageSize' ] = 0;
$request [ 'CurrentPageIndex' ] = 0;
$request [ 'SelectSql' ] = $this->_conditionalQuery( $since ) . ' ORDER BY Sales.SaleDate;';
try {
$result = $this->_endPoint->SelectDataXml( array ( 'Request' => $request ) );
} catch ( SoapFault $fault ) {
echo 'ERROR: [' . $fault->faultcode . '] ' . $fault->faultstring . '.';
exit;
} catch ( Exception $e ) {
echo 'ERROR: ' . $e->getMessage() . '.';
exit;
}
echo '<p>';
var_dump ($result->SelectDataXmlResult);
echo '</p>';
return $result->SelectDataXmlResult;
}
}
有问题的方法是getSomething。 $since 变量无关紧要,它在查询中用作检索数据的截止日期(为此我有一个私有 _conditionalQuery( $since ) 方法)。
我在浏览器上得到的 var_dump ($result->SelectDataXmlResult) 的输出是:
object(MindbodyDataServiceResponse)[22]
public 'Status' => string 'Success' (length=7)
public 'ErrorCode' => int 200
public 'XMLDetail' => string 'Full' (length=4)
public 'ResultCount' => int 0
public 'CurrentPageIndex' => int 0
public 'TotalPageCount' => int 0
public 'Results' =>
object(stdClass)[23]
public 'Row' =>
array (size=4)
0 =>
object(stdClass)[24]
...
1 =>
object(stdClass)[25]
...
2 =>
object(stdClass)[26]
...
3 =>
object(stdClass)[27]
...
已编辑
这是服务器的响应:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<SelectDataXmlResponse xmlns="http://clients.mindbodyonline.com/api/0_5">
<SelectDataXmlResult>
<Status>Success</Status>
<ErrorCode>200</ErrorCode>
<XMLDetail>Bare</XMLDetail>
<ResultCount>0</ResultCount>
<CurrentPageIndex>0</CurrentPageIndex>
<TotalPageCount>0</TotalPageCount>
<Results>
<Row>
<Column1>REMOVED</Column1>...(more columns)
</Row>
<Row>
<Column1>REMOVED</Column1>...(more columns)
</Row>
<Row>
<Column1>REMOVED</Column1>...(more columns)
</Row>
<Row>
<Column1>REMOVED</Column1>...(more columns)
</Row>
</Results>
</SelectDataXmlResult>
</SelectDataXmlResponse>
</soap:Body>
</soap:Envelope>
我删除了每个 Row 元素的实际内容,因为它是客户数据,但它们是格式良好的 XML 元素。正是那些我作为空 stdClass 对象获得的元素,我应该在其中获得 stdClass 对象,其成员与 Row 元素的子元素具有 1:1 对应关系。
【问题讨论】:
-
你需要一个关于如何通过soapclient调用方法的例子吗?
-
不,我已经做得很好了。正如我上面所说的,问题在于调用返回了不应返回的空对象。
-
你能把你的代码贴在这里吗?
-
添加了代码,加上 var_dump 的输出 :)
-
不可能,除了作为服务的消费者之外,我无法访问服务器。无论如何,我已经解决了这个问题。似乎 PHP 的 SoapClient 内部解析器在某些条件下(我碰巧遇到)默默地失败了。我所做的是丢弃我正在获取的对象并请求原始 XML 响应,我将其传递给 simplexml_load_string 例程以获取我可以实际使用的对象。稍后我将发布代码,因为由于 StackOverflow 的限制,我目前无法发布。
标签: php soap-client