php SoapVar未设置属性

php SoapVar未设置属性,php,soap,Php,Soap,我正在尝试向soap请求添加一些属性。PHP.net()等网站上的顶级评论都说了同样的话: $param = array( "_" => 'value', 'attrName' => 'attributeName' ); $p = new SoapVar($param, SOAP_ENC_OBJECT); 应该回来 <param attrName="attributeName">value</param> 值 这将非常好,除非当我运行这段

我正在尝试向soap请求添加一些属性。PHP.net()等网站上的顶级评论都说了同样的话:

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

<param attrName="attributeName">value</param>
这将非常好,除非当我运行这段代码时,我得到以下XML:

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

价值
属性名称

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

目前,我正在使用
DOMDocument
对象创建节点。希望有一个更简单的方法,但为了回答这个问题并提供一个解决方法,下面是:

$dom = new DOMDocument("1.0", "utf-8");
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$param = $dom->createElement('param');
$paramAttr = $dom->createAttribute('attrName');
$paramAttr->value = "attributeName";
$param->value = "value";
$param->appendChild($paramAttr);
$dom->appendChild($param);
$soap->param = new SoapVar($dom->saveXML($dom->documentElement), XSD_ANYXML);
所以并不理想。另一种方法是自己编写XML:

$soap->param = new SoapVar("<param attrName='attributeName'>value</param>", XSD_ANYXML);
$soap->param=newsoapvar(“value”,XSD\u ANYXML);

这两种方式我都不喜欢,但当你有了最后期限,你就去做有效的事情。

我知道这是一个老问题,但我想为任何偶然发现这篇文章的人提供一个答案。我遇到了与mounty相同的问题,并且能够使用不需要
XSD_ANYXML
的解决方案来解决它。我无法使用
array
方法使
SoapVar
工作,但能够使用与类属性相同的键使其工作。例如,使用以下代码:

class MyParam {
  public $_;
  public $attrName;

  public function __construct($paramValue, $attrValue)
  {
    $this->_ = $paramValue;
    $this->attrName = $attrValue;
  }
}

$soap->param = new MyParam("value", "attributeName");

只有在使用库从包含需要属性的数据类型的WSDL生成PHP类并看到使用了此模式后,我才能理解这一点。

是,你不是唯一一个有这个问题的人——我看到过无数的帖子,人们声称用SOAP_ENC_对象传递给SoapVar的数组解决了这个问题,而其他人则在相同的帖子上声明其他问题。文档中也不清楚原因(除了我一年前在php.net评论部分发表的文章)

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

$param = array(
    "_" => 'value',
    'attrName' => 'attributeName'
);
$p = new SoapVar($param, SOAP_ENC_OBJECT);
文档没有说明的内容:这种语法可能会产生两种不同的结果(事实上,甚至更多:PHP SOAP可能以八种不同的方式来表达它)。正如您可能看到的,上面的代码是模棱两可的:上面的代码中有什么说“attrName”是一个属性而不是一个元素?没有什么。上面的代码没有足够的信息让SoapClient决定什么是“attrName”,因此它默认为“一个元素”

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

基本上,为了实现您想要的,您需要在块中的适当部分中具有文档/文字模式的WSDL文件


有些人声称在属性的数组使用方面取得了成功,而另一些人说“它不起作用”的原因完全在于他们的设置:有些人有WSDL文件要使用,有些人只是尝试使用新的SoapClient(null,数组(…);(这当然不符合他们的期望)

重要的一点是,只需添加属性,它就会根据wsdl自动映射到属性。整洁的特性——这样,您就可以只使用对象结构,并让它们自动映射到节点/属性。正如Vladimir在上面指出的,这将只在WSDL模式下工作!