Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
788 views
in Technique[技术] by (71.8m points)

soap - php SoapVar not setting attributes

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

should return

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

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

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

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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).

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

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 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.

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.

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)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...