【问题标题】:php SoapVar not setting attributesphp SoapVar 未设置属性
【发布时间】:2014-07-21 17:16:54
【问题描述】:

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

$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 年以来,关于这一点功能的文档是否发生了变化?

【问题讨论】:

    标签: php soap


    【解决方案1】:

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

    面对同样的问题,我已经阅读了 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 文件要使用,有些人只是尝试做 new SoapClient(null,大批(...)); (当然没有达到他们的预期)

    【讨论】:

    • 很好,只是添加它也适用于对象,只需添加属性,它将根据 wsdl自动映射到属性。简洁的功能 - 这样您就可以只使用对象结构并将它们自动映射到节点/属性。
    【解决方案2】:

    目前我使用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);
    

    我不喜欢任何一种方式,但是当你有最后期限时,你会选择可行的。

    【讨论】:

      【解决方案3】:

      我知道这是一个老问题,但我想为其他偶然发现这篇文章的人提供一个答案。我遇到了与 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");
      

      我只是在使用wsdl2phpgenerator 库从包含需要属性的数据类型的 WSDL 生成 PHP 类并看到这种模式被使用后才弄清楚这一点。

      【讨论】:

      • 正如 Vladimir 上面指出的,这仅适用于 WSDL 模式!
      猜你喜欢
      • 2011-11-05
      • 1970-01-01
      • 1970-01-01
      • 2012-06-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-25
      • 2011-10-14
      • 1970-01-01
      相关资源
      最近更新 更多