php SoapVar 未设置属性

2021-12-24 00:00:00 php soap

我正在尝试向soap请求添加一些属性.PHP.net 上评分最高的评论 (http://php.net/manual/en/soapvar.soapvar.php) 和这里和这里 在 SO 上都说同样的话:

I'm trying to add a few attributes to a soap request. Top rated comment on PHP.net (http://php.net/manual/en/soapvar.soapvar.php) and here and here on SO all say the same thing:

$param = array(
    "_" => 'value',
    'attrName' => 'attributeName'
);
$p = new SoapVar($param, SOAP_ENC_OBJECT);

应该返回

<param attrName="attributeName">value</param>

这会很棒,除非当我运行该代码块时,我得到了这个 XML:

Which would be great, except when I run that block of code, I get this XML:

<param>
    <_>value</_>
    <attrName>attributeName</attrName>
</param>

这显然是错误的.我肯定不是世界上唯一有这个问题的人吗?自 2011 年以来,关于那一点点功能的文档是否发生了变化?

which is clearly wrong. Surely I'm not the only person in the world to have this problem? Did the documentation on that little bit of functionality change since 2011?

推荐答案

是的,您不是唯一遇到此问题的人 - 我看过无数帖子,人们声称使用 SOAP_ENC_OBJECT 传递给 SoapVar 的数组解决了这个问题而其他人在相同的帖子上声称不同.并且文档并不清楚原因(除了我一年前在 php.net 评论部分的帖子).

Yes, you are not the only one who having this issue - I have seen countless number of posts where people claim that array passed to SoapVar with SOAP_ENC_OBJECT solves the issue while other people claim otherwise on the same posts. And documentation is not clear on the reasons (apart from my post year ago in comments section of php.net).

面对同样的问题,我已经阅读了 PHP SOAP 扩展的源代码.基本上你使用的语法是绝对正确的:

Facing the same issue I have read the sources of PHP SOAP extension. Basically the syntax you have used is absolutely correct:

$param = array(
    "_" => 'value',
    'attrName' => 'attributeName'
);
$p = new SoapVar($param, SOAP_ENC_OBJECT);

文档没有说明:这种语法可能会产生两种不同的结果(事实上甚至更多:PHP SOAP 可以用八种不同的方式表达它).正如您可能看到的,上面的代码是模棱两可的:上面的代码中是什么说attrName"是一个属性而不是一个元素?没有什么.上面的代码只是没有足够的信息让 SoapClient 决定attrName"是什么,所以它默认为一个元素".

What the documentation does not say: this syntax may produce two different results (and in fact even more: PHP SOAP may express it in eight different ways). And as you may see the code above is ambiguous: what in the code above says that 'attrName' is an attribute and not an element? Nothing. The code above just don't have sufficient amount of information for SoapClient to decide what 'attrName' is and so it defaults to "an element".

SoapClient 可以在两种模式下运行:非 WSDL 和 WSDL.在前一种模式下,您永远不会得到您想要的结果:SoapClient 依赖类型信息将数组元素转换为属性.由于非 WSDL 模式中不存在类型信息,因此 SoapClient 将提供的数组表示为一组元素 - 正是您得到的.在 WSDL 模式中存在类型信息,因此 SoapClient 知道元素和属性名称,并且可以将它们与数组索引进行匹配.所以如果你想要你的属性,你必须让你的 SoapClient 处于 WSDL 模式.

SoapClient may operate in two modes: non-WSDL and WSDL. In former mode you would never get the result you want: SoapClient relies on type information in order to turn array element into attribute. As type information is not present in non-WSDL mode SoapClient represents the provided array as set of elements - exactly what you got. In WSDL mode type information is present and therefore SoapClient knows elements and attributes names and may match them to array indexes. So you MUST have your SoapClient in WSDL mode if you want your attributes.

基本上为了实现你想要的,你需要在 <xsd:attribute name="attrName" type="xsd:string"/> 文档/文字模式下的 WSDL 文件在 <xsd 的适当部分:架构> 块.

Basically in order to achieve what you want you need to have WSDL file in document/literal mode with <xsd:attribute name="attrName" type="xsd:string"/> in appropriate section in <xsd:schema> block.

为什么有些人声称属性数组使用成功而其他人说它不起作用"的原因仅在于他们的设置:有些人有 WSDL 文件要使用,有些人只是想执行 new SoapClient(null,大批(...));(这当然没有达到他们的期望)

The reason why some people claim success about array use for attributes and other people say "It does not work" lies solely in their setup: some people have WSDL files to consume, some people just trying to do new SoapClient(null, array(...)); (which of course fails their expectations)

相关文章