You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP SOAP服务返回同名带属性元素数组的格式匹配问题

解决PHP SOAP服务返回与输入一致的带属性XML结构问题

我完全懂你碰到的麻烦——当你直接返回PHP解析后的SOAP请求对象时,原本带多个属性的<policy>元素居然变成了空标签,完全没保留原来的结构和属性值。这是因为PHP的SOAP扩展默认的对象序列化逻辑,没办法正确识别那些从XML属性转换来的对象属性,得手动用SoapVar来构建响应结构才行。

问题根源

PHP解析SOAP请求时,会把带属性的XML元素(比如你的<policy>)转换成带对应属性的stdClass对象,但返回响应时,SOAP扩展默认只会把数组当成重复元素处理,却不会自动把对象里的属性映射回XML元素的属性,所以才生成了空的<policy />标签。

解决方案:手动构建带属性的SOAP响应

我们需要遍历每个policy对象,把它们转换成带属性的SoapVar,再把整个响应结构正确包装,这样就能生成和输入一致的XML了。

方法1:PHP 8.0+ 版本(支持SoapAttribute)

<?php
class Example {
    public function SendPolicies($request) {
        // 处理每个policy对象,转换为带属性的SoapVar
        $policySoapVars = [];
        foreach ($request->policy as $policy) {
            // 注意:解析时polizzenNr被转成了Nr,这里要修正回原属性名
            $attributes = [];
            foreach ($policy as $key => $value) {
                $attributeName = $key === 'Nr' ? 'polizzenNr' : $key;
                $attributes[] = new SoapAttribute($attributeName, '', $value);
            }

            // 创建带属性的policy元素SoapVar
            $policyVar = new SoapVar(
                '', // policy元素没有子节点,内容为空
                XSD_ANYXML,
                null,
                null,
                'policy',
                'https://customer-soap.example.com/?WSDL', // 对应你的命名空间
                $attributes
            );
            $policySoapVars[] = $policyVar;
        }

        // 构建完整的响应结构
        $responseData = [
            'sesid' => new SoapVar(
                $request->sesid,
                XSD_STRING,
                null,
                null,
                'sesid',
                'https://customer-soap.example.com/?WSDL'
            ),
            'policy' => $policySoapVars
        ];

        // 包装成输出对应的根元素
        $response = new SoapVar(
            $responseData,
            SOAP_ENC_OBJECT,
            null,
            null,
            'SendPoliciesRequestOutput',
            'https://customer-soap.example.com/?WSDL'
        );

        return $response;
    }
}

方法2:兼容PHP 8.0以下版本(手动构造XML片段)

如果你的PHP版本低于8.0,没有SoapAttribute类,可以直接用XSD_ANYXML构造XML字符串:

<?php
class Example {
    public function SendPolicies($request) {
        $policySoapVars = [];
        foreach ($request->policy as $policy) {
            // 构建属性字符串
            $attrString = '';
            foreach ($policy as $key => $value) {
                $attributeName = $key === 'Nr' ? 'polizzenNr' : $key;
                // 转义XML特殊字符,避免格式错误
                $attrString .= " $attributeName=\"" . htmlspecialchars($value, ENT_QUOTES) . "\"";
            }
            // 直接构造policy元素的XML
            $policyXml = "<policy$attrString />";
            $policySoapVars[] = new SoapVar($policyXml, XSD_ANYXML);
        }

        // 构建响应
        $responseXml = '<SendPoliciesRequestOutput xmlns="https://customer-soap.example.com/?WSDL">';
        $responseXml .= "<sesid>" . htmlspecialchars($request->sesid, ENT_QUOTES) . "</sesid>";
        $responseXml .= implode('', $policySoapVars);
        $responseXml .= '</SendPoliciesRequestOutput>';

        return new SoapVar($responseXml, XSD_ANYXML);
    }
}

关键注意点

  • 一定要修正属性名:你的请求里polizzenNr被PHP解析成了Nr,所以在构建响应时要把这个属性名改回去,否则返回的XML属性名会不对。
  • 记得转义XML特殊字符:如果属性值里包含<、>、"等字符,必须用htmlspecialchars转义,避免生成无效的XML。

这样处理后,你的SOAP服务返回的XML就会和输入的结构完全一致,包含所有带属性的<policy>元素啦。

内容的提问来源于stack exchange,提问作者Theo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:49:53