SoapClient - 递归地删除请求中生成的BOGUS标记

时间:2014-08-13 23:23:34

标签: php soap

我非常惊讶这个问题并不普遍,但谷歌只有几个答案。这些特定于单个请求,其中解决方案是在发送之前手动调整Soap参数的结构。我首先明确表示我正在为多个服务呼叫开发中央网关。这些调用唯一的共同点就是它们将中心方法传递给了一个多维数组的参数。然后,中央方法调用SoapClient。

如果需要,我可以单独构建数组。我不能像建议here那样构建单独的Soap param对象。

在这个例子中我有以下数组:

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;
    }

除了我们使用句点数字数组之外,大部分都可以正常工作。 (上面数组中两个数字索引项的集合)。我在请求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>

这几乎是正确的。如果仅完全省略<BOGUS>级别标记。目前服务是抱怨结构(我无法控制服务)

关于如何让我的递归函数识别这样的集合的任何想法?真的,我认为这更像是一个逻辑挑战,而不是特定于肥皂的那个。

1 个答案:

答案 0 :(得分:3)

可能这个问题依赖于单个数组结构,但是下面的递归函数对我来说对我每个数组都有用:

// 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);
}