Php SoapClient-递归地去除请求中生成的虚假标记
我感到非常惊讶的是,这个问题并没有更普遍,但在谷歌只有几个答案。这些都非常特定于一个请求,解决方案是在发送前手动调整Soap参数的结构。首先,我要明确我正在为多个服务呼叫开发一个中央网关。这些调用唯一的共同点是,它们向中心方法传递一个多维参数数组。然后,中心方法进行SoapClient调用 如果需要,我可以单独构造阵列。我无法按照建议构建单个Soap参数对象 在此实例中,我有以下数组:Php SoapClient-递归地去除请求中生成的虚假标记,php,soap,Php,Soap,我感到非常惊讶的是,这个问题并没有更普遍,但在谷歌只有几个答案。这些都非常特定于一个请求,解决方案是在发送前手动调整Soap参数的结构。首先,我要明确我正在为多个服务呼叫开发一个中央网关。这些调用唯一的共同点是,它们向中心方法传递一个多维参数数组。然后,中心方法进行SoapClient调用 如果需要,我可以单独构造阵列。我无法按照建议构建单个Soap参数对象 在此实例中,我有以下数组: Array ( [userId] => 336790 [locationId] =>
Array
(
[userId] => 336790
[locationId] => 47862
[schedule] => Array
(
[cipTime] => 15
[confirmed] => 1
[cycle] => Twice per Day
[periods] => Array
(
[0] => Array
(
[WS_Period] => Array
(
[duration] => 300
[startTime] => 15
)
)
[1] => Array
(
[WS_Period] => Array
(
[duration] => 240
[startTime] => 870
)
)
)
[startDate] => 16-08-2014
)
)
我试图创建一个递归函数来循环这个数组并构建一个有效的Soap请求对象
// Encode the params array into a format that the soap client can use.
// This is to avoid the dreaded <BOGUS> tags that the PHP SoapClient generates in the request.
private function encodeSoapParams(Array $params) {
// The entire request should be an array
$request = array();
foreach ($params as $name => $value) {
if(is_scalar($value)) {
$request[$name] = new SoapVar($value, XSD_STRING, null, null, $name);
} elseif(is_array($value)) {
$newValue = $this->encodeSoapParams($value);
$request[$name] = new SoapVar($newValue, SOAP_ENC_OBJECT, null, null, $name);
}
}
return $request;
}
//将params数组编码为soap客户端可以使用的格式。
//这是为了避免PHP SoapClient在请求中生成可怕的标记。
私有函数编码soapparams(数组$params){
//整个请求应该是一个数组
$request=array();
foreach($name=>$value的参数){
if(是_标量($value)){
$request[$name]=newsoapvar($value,XSD_字符串,null,null,$name);
}elseif(is_数组($value)){
$newValue=$this->encodeSoapParams($value);
$request[$name]=newsoapvar($newValue,SOAP\u ENC\u对象,null,null,$name);
}
}
返回$request;
}
这在大多数情况下都很好,除了我们使用周期数字数组。(上述数组中两个数字索引项的集合)。我在请求XML中得到的结果是:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="urn:Blah/WebService/">
<env:Body>
<ns1:updateSchedule>
<userId>336790</userId>
<locationId>47862</locationId>
<schedule>
<cipTime>15</cipTime>
<confirmed>1</confirmed>
<cycle>Twice per Day</cycle>
<periods>
<BOGUS>
<WS_Period>
<duration>300</duration>
<startTime>15</startTime>
</WS_Period>
</BOGUS>
<BOGUS>
<WS_Period>
<duration>240</duration>
<startTime>870</startTime>
</WS_Period>
</BOGUS>
</periods>
<startDate>16-08-2014</startDate>
</schedule>
</ns1:updateSchedule>
</env:Body>
</env:Envelope>
336790
47862
15
1.
每天两次
300
15
240
870
16-08-2014
这几乎是正确的。如果只完全省略了
级别标记。目前,该服务正在抱怨结构(我无法控制该服务)
关于如何让递归函数识别这样的集合,有什么想法吗?实际上,我认为这更像是一个逻辑挑战,而不是一个特定于Soap的挑战。这个问题可能取决于单个数组结构,但下面的递归函数对我抛出的每个数组都有效:
// Encode the params array into a format that the soap client can use.
// This is to avoid the dreaded <BOGUS> tags that the PHP SoapClient generates in the request.
// All PI call param arrays should pass through here first
private function encodeSoapParams(Array $params) {
// The entire request should be an array
$request = array();
foreach($params as $name => $value) {
if(is_scalar($value)) {
$request[$name] = new SoapVar($value, XSD_STRING, null, null, $name);
} else {
if($this->IsArrayAllKeyInt($value)) {
$collection = array();
foreach($value as $key => $itemVal) {
//$collection[] = $itemVal;
if(is_scalar($itemVal)) {
$collection[] = new SoapVar($itemVal, XSD_STRING, null, null, $name);
} else {
// We have an array
$subKey = key($itemVal);
$collection[] = new SoapVar($itemVal[$subKey], SOAP_ENC_OBJECT, null, null, key($itemVal));
}
}
$request[$name] = new SoapVar($collection,SOAP_ENC_OBJECT,null,null, $name);
} else {
$newValue = $this->encodeSoapParams($value);
$request[$name] = new SoapVar($newValue, SOAP_ENC_OBJECT, null, null, $name);
}
}
}
return $request;
}
// See if a given array has all Int keys.
// See encodeSoapParams()
function IsArrayAllKeyInt($InputArray)
{
if(!is_array($InputArray))
{
return false;
}
if(count($InputArray) <= 0)
{
return true;
}
return array_unique(array_map("is_int", array_keys($InputArray))) === array(true);
}
//将params数组编码为soap客户端可以使用的格式。
//这是为了避免PHP SoapClient在请求中生成可怕的标记。
//所有PI调用参数数组都应首先通过此处
私有函数编码soapparams(数组$params){
//整个请求应该是一个数组
$request=array();
foreach($name=>$value的参数){
if(是_标量($value)){
$request[$name]=newsoapvar($value,XSD_字符串,null,null,$name);
}否则{
如果($this->IsArrayAllKeyInt($value)){
$collection=array();
foreach($key=>$itemVal的值){
//$collection[]=$itemVal;
if(是_标量($itemVal)){
$collection[]=newsoapvar($itemVal,XSD_字符串,null,null,$name);
}否则{
//我们有一个数组
$subKey=key($itemVal);
$collection[]=newsoapvar($itemVal[$subKey],SOAP_ENC_对象,null,null,key($itemVal));
}
}
$request[$name]=newsoapvar($collection,SOAP\u ENC\u OBJECT,null,null,$name);
}否则{
$newValue=$this->encodeSoapParams($value);
$request[$name]=newsoapvar($newValue,SOAP\u ENC\u对象,null,null,$name);
}
}
}
返回$request;
}
//查看给定数组是否具有所有Int键。
//请参见encodeSoapParams()
函数IsArrayAllKeyInt($InputArray)
{
如果(!is_数组($InputArray))
{
返回false;
}
如果(count($InputArray)如何实现此功能,请指导我..?或更新完整代码。