Zend SOAP:将默认数组元素名称“item”更改为 WSDL 中复杂类型的类名称
Posted
技术标签:
【中文标题】Zend SOAP:将默认数组元素名称“item”更改为 WSDL 中复杂类型的类名称【英文标题】:Zend SOAP: Change the default array element name "item" to class name of complex type in WSDL 【发布时间】:2015-07-08 14:40:15 【问题描述】:这个问题可能会被问到,但它很难搜索,我找不到任何关于它的信息。而且问起来也不容易。
我正在使用 Zend SOAP 的自动发现功能重新创建我们的旧 SOAP 接口(因为切换到微服务并重新处理所有内容)。
到目前为止,它就像一个魅力。但是在使用列表/数组时,我在重新创建某些服务的 SOAP 响应时遇到了一个问题。
SOAP 请求的旧响应 XML 如下所示。它在<SMSEntries>
列表中包含两个<SMSEntry>
。
<SOAP-ENV:Envelope>
<SOAP-ENV:Body>
<ns1:getSMSByTimeSpanResult>
<AmountOfEntries>2</AmountOfEntries>
<SMSEntries>
<SMSEntry></SMSEntry>
<SMSEntry></SMSEntry>
</SMSEntries>
</ns1:getSMSByTimeSpanResult>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
但是重新创建的响应看起来像这样。它在<SMSentries>
列表中包含两个<item>
s 类型为SMSEntry
。
<SOAP-ENV:Envelope>
<SOAP-ENV:Body>
<ns1:getSMSByTimeSpanResponse>
<return xsi:type="ns1:getSMSByTimeSpanResponse">
<AmountOfEntries xsi:type="xsd:int">2</AmountOfEntries>
<SMSEntries SOAP-ENC:arrayType="ns1:SMSEntry[2]" xsi:type="ns1:ArrayOfSMSEntry">
<item xsi:type="ns1:SMSEntry"></item>
<item xsi:type="ns1:SMSEntry"></item>
</SMSEntries>
<DataEx xsi:nil="true"/>
</return>
</ns1:getSMSByTimeSpanResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
我无法控制客户。他们可能会通过比较字符串来检查SMSEntry
。我想使用类名 SMSEntry
作为 XML 标记名。
其次,我想省略额外的,包装所有内容,<return>
标签。
我正在使用这样的自动发现:
use Zend\Soap\AutoDiscover;
use Zend\Soap\Wsdl\ComplexTypeStrategy\ArrayOfTypeComplex;
$autoDiscover = new AutoDiscover(new ArrayOfTypeComplex());
$autoDiscover->setClass(new Standard($sm));
getSMSByTimeSpanResponse 的定义如下:
标准.php
/**
* Class getSMSByTimeSpanResponse
*
* @package LgxServiceManager\Service
*/
class getSMSByTimeSpanResponse
/**
* @var int
*/
public $AmountOfEntries;
/**
* @var \LgxServiceManager\Service\SMSEntry[]
*/
public $SMSEntries;
/**
* Class SMSEntry
*
* @package LgxServiceManager\Service
*/
class SMSEntry
有人知道怎么做吗?
我在library\Zend\Soap\Wsdl\ComplexTypeStrategy\ArrayOfTypeSequence.php:122
中找到了一些代码
_addSequenceType()
方法设置硬编码属性的地方:
$element->setAttribute('name', 'item');
但这是“序列”类型,而不是我正在使用的“复杂”类型......
提前谢谢你, 菲利普
\编辑
哦,伙计...我刚刚发现了另一个我不知道如何使用 Zend SOAP 的自动发现创建的结构...
<mainMember1>SERIALNUMBER</mainMember1>
<mainMember2>NAMEOFPRODUCT</mainMember2>
<mainMember3>000000-000-0</mainMember3>
<Rules>
<RuleEntry>
<singleValue>allow</singleValue>
<ResourceList>
<Name>generic</Name>
<ResourceEntry>[...]</ResourceEntry>
<ResourceEntry>[...]</ResourceEntry>
<ResourceEntry>[...]</ResourceEntry>
</ResourceList>
<ResourceList>
<Name>default</Name>
<ResourceEntry>[...]</ResourceEntry>
<ResourceEntry>[...]</ResourceEntry>
<ResourceEntry>[...]</ResourceEntry>
</ResourceList>
</RuleEntry>
</Rules>
如您所见,<RuleEntry>
内部有一个<singleValue>
,但有多个<ResourceList>
s。资源列表内部使用相同的结构:一个<Name>
和多个<ResourceEntry>
...
这甚至可以通过自动发现来处理吗?
【问题讨论】:
也许这会给你一些提示:***.com/questions/17307571/… 谢谢。我自己弄清楚了,并按照我的问题代码中的描述使用了它。我的 WSDL 看起来很好。但是响应 XML 比那些“项目”元素... 无论答案如何,我都能感受到你的痛苦。任何时候有人暗示将来要使用 SOAP,你必须非常快地喊出“使用 REST!”。在他们身上。 【参考方案1】:我知道这是一个旧线程,但我正在努力帮助那些遇到与我相同问题的追随者。
现在我们使用 Laminas,但原理是一样的。
解决原始问题的另一种方法是对 供应商\Laminas\Laminas-Soap\src\Wsdl\ComplexTypeStrategy\ArrayOfTypeSequence.php:124 用这样的代码:
// Paulo
// $element->setAttribute('name', 'item'); // Original Code
$element->setAttribute('name', substr($childType, 4));
// Paulo End
希望对大家有帮助
【讨论】:
【参考方案2】:对于仍有上述问题的任何人:
stdClass()
的默认响应如下:
$array = ['lets', 'test', 'it'];
$response = new stdClass();
$response->results = $array;
会是这样的:
<return xsi:type="SOAP-ENC:Struct">
<results SOAP-ENC:arrayType="xsd:string[3]" xsi:type="SOAP-ENC:Array">
<item xsi:type="xsd:string">lets</item>
<item xsi:type="xsd:string">test</item>
<item xsi:type="xsd:string">it</item>
</results>
</return>
我们能做什么——我们可以将数组更改为ArrayObject()
:
$array = ['lets', 'test', 'it'];
$response = new stdClass();
$response->results = new ArrayObject();
foreach($array as $item)
$response->results->append($item);
返回:
<return xsi:type="SOAP-ENC:Struct">
<results xsi:type="SOAP-ENC:Struct">
<BOGUS xsi:type="xsd:string">lets</BOGUS>
<BOGUS xsi:type="xsd:string">test</BOGUS>
<BOGUS xsi:type="xsd:string">it</BOGUS>
</results>
</return>
最后是锦上添花:
$array = ['lets', 'test', 'it'];
$response = new stdClass();
$response->results = new ArrayObject();
foreach($array as $item)
$soapVar = new SoapVar($item,XSD_STRING,NULL,NULL,'result');
$response->results->append($soapVar);
它会返回:
<return xsi:type="SOAP-ENC:Struct">
<results xsi:type="SOAP-ENC:Struct">
<result xsi:type="xsd:string">lets</result>
<result xsi:type="xsd:string">test</result>
<result xsi:type="xsd:string">it</result>
</results>
</return>
如您所见,第五个参数告诉了 xml 元素的键是什么。您还需要注意第二个参数,因为它告诉变量的类型。你可以在这里找到更多: https://secure.php.net/manual/en/class.soapvar.php
【讨论】:
以上是关于Zend SOAP:将默认数组元素名称“item”更改为 WSDL 中复杂类型的类名称的主要内容,如果未能解决你的问题,请参考以下文章