我正在试验一个公共 SOAP API,以准备测试我们正在工作的内部 SOAP API。我在处理自动将方法名称与参数名称关联时遇到了问题。
更具体地说,我正在针对http://www.webservicex.net/stockquote.asmx?WSDL进行测试,我想做的是编写一个可以在 Behat 中使用的函数,以便我们的 QA 人员可以轻松地创建指定新函数的新场景(因为它们是创建的)而无需我每次都编写一个新函数。
为此,我为 SoapClient::__soapCall() 构建了一个函数包装器。我已经能够调用特定函数来工作,例如:
<?php
public function iGetAQuoteFor($symbol) {
$response = $this->client->GetQuote(array('symbol' => $symbol));
$quote = simplexml_load_string($response->GetQuoteResult)->Stock;
echo "Quote:\n" . print_r($quote, true) . "\n";
}
?>
所以很明显,我需要识别我发送到 SOAP 服务的参数才能使其生效。但要做到这一点,我需要能够将函数名称映射到选项名称。我曾尝试使用 SimpleXML 处理 WSDL,但我很难浏览其结果。当我使用 SimpleXML 函数“children”并指定“wsdl”命名空间时,我尝试了很多不同的方法并取得了一些进展。但是我得到的结果并没有更好。
这是我的肥皂调用函数(写为 Behat 上下文):
/**
* Calls a specific SOAP function (defined in the WSDL).
*
* @param string $functionName
* @param string $options (optional, no implemented yet)
*
* @Given /^I make a SOAP call to "([^"]*)" with "([^"]*)"$/
* @Given /^I make a SOAP call to "([^"]*)"$/
*/
public function iMakeASOAPCallTo($functionName, $passedOptions = NULL) {
//Deal with the options
$options = array($passedOptions);
if (stristr($passedOptions, ',')) {
$options = explode(',', $passedOptions);
}
else if (empty($passedOptions)) {
$options = array();
}
//Also should try to figure out how to match the function call to the option wrapper
#Function placeholder
//Attempt to make the call
try {
$result = $this->client->__soapCall($functionName, $options);
}
catch (\Exception $e) {
throw new Exception("Failed to call SOAP function.");
}
//Process the result
if (!empty($result)) {
$result = $this->decodeSOAPResult($functionName, $result);
if (!empty($result)) {
echo " It returns:\n" . print_r($result, true) . "\n";
}
else {
throw new Exception("Invalid result from function call.");
}
}
else {
throw new Exception("Failed result or exception from function call.");
}
}
这是我的函数,它在建立与肥皂服务的连接后尝试获取架构详细信息。
private function buildSchemaDetails() {
$xml = simplexml_load_file($this->soapURL);
echo "\n" . print_r($xml, true) . "\n";
echo "For the ns:\n";
$element = $xml->getDocNamespaces();
echo "\n" . print_r($element, true) . "\n";
$element = $xml->children('wsdl', true)->types->children();
echo "\n" . print_r($element, true) . "\n";
die();
}
如您所见,我在那里有一些测试代码。现在很难看,但我需要弄清楚如何处理它。如果有人知道有一个工具可以提前为我完成所有这些工作,那就太棒了。
本质上,我想要做的是在尝试调用函数之前识别函数的参数。如果函数只有一个参数,那么我只想根据我正在调用的函数将输入的变量映射到一个参数名称,然后调用它。
这在 Behat 中在编写功能和场景时很有用,因为它允许我编写 Gherkin 样式的行,例如“然后我用“GOOG”对“GetQuote”进行 SOAP 调用,而不必担心指定名称参数。在这个 WSDL 的情况下,我发现不能只传递一个变量并完成它有点可笑。我见过不需要指定参数名称的另一个 SOAP 服务。
因此,能够理解调用结构是简化所有这些的关键。