在 PHP 7.4 中生成 SOAP 数组

2024-01-04

我一直在工作项目中使用 SOAP API(我很幸运!),WSDL 基本上毫无意义,因为请求的正文是<any />所以我必须生成 SOAP 请求而不是使用 classmap 选项。我正在使用这种方式https://www.fischco.org/technica/2011/php-soap/ https://www.fischco.org/technica/2011/php-soap/生成一个对象数组,否则,正如帖子中所说,我得到了<BOGUS> tags.

这几乎就是我多年来所做的事情,从我所看到的情况来看,这似乎也是很多其他人所做的事情http://www.mm-newmedia.de/2017/10/php-und-bipro-sich-wiederholende-elemente-im-soap-request/ http://www.mm-newmedia.de/2017/10/php-und-bipro-sich-wiederholende-elemente-im-soap-request/ and http://andrecatita.com/code-snippets/php-soap-repeated-element-name/ http://andrecatita.com/code-snippets/php-soap-repeated-element-name/

一切正常,但我意识到我仍在使用 7.3 docker 映像,因此升级到 7.4,这不再有效,我只获取数组的标签,而不是单个项目,我认为这是因为 7.4 中的这一更改。

Calling get_object_vars()现在,在数组对象实例上将始终返回数组对象本身(或子类)的属性。以前它返回包装数组/对象的值,除非ArrayObject::STD_PROP_LIST指定了标志。

以前有人遇到过这个问题吗?昨天我花了整个下午试图弄清楚,但我完全被难住了

这是一个演示此行为的示例客户端

<?php

class Location
{
    public $Name;
}

// Overwrite the client so it doesn't actually make a request
class DebugSoapClient extends SoapClient
{
    public function __construct(string $wsdl, array $options = [])
    {
        $options = array_merge([
            'cache_wsdl'   => WSDL_CACHE_NONE,
            'exceptions'   => true,
            'features'     => SOAP_SINGLE_ELEMENT_ARRAYS,
            'soap_version' => SOAP_1_1,
            'trace'        => true,
        ], $options);

        parent::__construct($wsdl, $options);
    }

    public function __doRequest($request, $location, $action, $version, $one_way = 0): string
    {
        return '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><SubmitWorkItemResponse xmlns="http://example.com/webservices/DataServices/v2/ServicesAccess"><SubmitWorkItemResult></SubmitWorkItemResult></SubmitWorkItemResponse></soap:Body></soap:Envelope>';
    }
}

// Create an instance of the client
$namespace = 'http://example.com/webservices/DataServices/v2/ServicesAccess';
$client = new DebugSoapClient(__DIR__ . '/example.wsdl');
$client->__setSoapHeaders(
    new SoapHeader(
        $namespace,
        'AuthenticationHeader',
        ['Username' => 'Foo', 'Password' => 'Bar', 'ClientName' => 'Baz']
    )
);

// Build the body of the request
$locations = new ArrayObject();
foreach (['London', 'New York', 'Paris', 'Rome'] as $l) {
    $loc = new Location();
    $loc->Name = new SoapVar($l, XSD_STRING, '', '', 'Name', $namespace);

    $locations->append(new SoapVar($loc, SOAP_ENC_OBJECT, '', '', 'Location', $namespace));
}

$request = [
    'SourceData' => [
        'any' => new SoapVar($locations, SOAP_ENC_OBJECT, '', '', 'Locations', $namespace)
    ],
];

// Dispatch the request
$client->__soapCall('SubmitWorkItem', [$request]);

// Get the request body
$doc = new DomDocument('1.0');
$doc->loadXML($client->__getLastRequest());
$doc->formatOutput = true;

echo $doc->saveXML();

这是一个简化的 WSDL

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://example.com/webservices/DataServices/v2/ServicesAccess" xmlns:s1="http://microsoft.com/wsdl/types/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" targetNamespace="http://example.com/webservices/DataServices/v2/ServicesAccess" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
    <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Data Services</wsdl:documentation>
    <wsdl:types>
        <s:schema elementFormDefault="qualified" targetNamespace="http://example.com/webservices/DataServices/v2/ServicesAccess">
            <s:import namespace="http://microsoft.com/wsdl/types/" />
            <s:element name="SubmitWorkItem">
                <s:complexType>
                    <s:sequence>
                        <s:element minOccurs="1" maxOccurs="1" name="SourceData" type="tns:Source" />
                    </s:sequence>
                </s:complexType>
            </s:element>
             <s:complexType name="Source">
                <s:sequence>
                    <s:any />
                </s:sequence>
            </s:complexType>
            <s:element name="AuthenticationHeader" type="tns:AuthenticationHeader" />
            <s:complexType name="AuthenticationHeader">
                <s:sequence>
                    <s:element minOccurs="0" maxOccurs="1" name="Username" type="s:string" />
                    <s:element minOccurs="0" maxOccurs="1" name="Password" type="s:string" />
                    <s:element minOccurs="0" maxOccurs="1" name="ClientName" type="s:string" />
                </s:sequence>
                <s:anyAttribute />
            </s:complexType>
            <s:element name="SubmitWorkItemResponse">
                <s:complexType>
                    <s:sequence>
                        <s:element minOccurs="0" maxOccurs="1" name="SubmitWorkItemResult">
                            <s:complexType mixed="true">
                                <s:sequence>
                                    <s:any />
                                </s:sequence>
                            </s:complexType>
                        </s:element>
                    </s:sequence>
                </s:complexType>
            </s:element>
        </s:schema>
        <s:schema elementFormDefault="qualified" targetNamespace="http://microsoft.com/wsdl/types/">
            <s:simpleType name="guid">
                <s:restriction base="s:string">
                    <s:pattern value="[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" />
                </s:restriction>
            </s:simpleType>
        </s:schema>
    </wsdl:types>
    <wsdl:message name="SubmitWorkItemSoapIn">
        <wsdl:part name="parameters" element="tns:SubmitWorkItem" />
    </wsdl:message>
    <wsdl:message name="SubmitWorkItemSoapOut">
        <wsdl:part name="parameters" element="tns:SubmitWorkItemResponse" />
    </wsdl:message>
    <wsdl:message name="SubmitWorkItemAuthenticationHeader">
        <wsdl:part name="AuthenticationHeader" element="tns:AuthenticationHeader" />
    </wsdl:message>
    <wsdl:portType name="ServicesAccessSoap">
        <wsdl:operation name="SubmitWorkItem">
            <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">This method accepts a single XML data block for processing.&lt;br&gt;Result returned synchronously.</wsdl:documentation>
            <wsdl:input message="tns:SubmitWorkItemSoapIn" />
            <wsdl:output message="tns:SubmitWorkItemSoapOut" />
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="ServicesAccessSoap" type="tns:ServicesAccessSoap">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name="SubmitWorkItem">
            <soap:operation soapAction="http://example.com/webservices/DataServices/v2/ServicesAccess/SubmitWorkItem" style="document" />
            <wsdl:input>
                <soap:body use="literal" />
                <soap:header message="tns:SubmitWorkItemAuthenticationHeader" part="AuthenticationHeader" use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:binding name="ServicesAccessSoap12" type="tns:ServicesAccessSoap">
        <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name="SubmitWorkItem">
            <soap12:operation soapAction="http://example.com/webservices/DataServices/v2/ServicesAccess/SubmitWorkItem" style="document" />
            <wsdl:input>
                <soap12:body use="literal" />
                <soap12:header message="tns:SubmitWorkItemAuthenticationHeader" part="AuthenticationHeader" use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap12:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="ServicesAccess">
        <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Data Services</wsdl:documentation>
        <wsdl:port name="ServicesAccessSoap" binding="tns:ServicesAccessSoap">
            <soap:address location="https://test.example.com/uat/ServicesAccess.asmx" />
        </wsdl:port>
        <wsdl:port name="ServicesAccessSoap12" binding="tns:ServicesAccessSoap12">
            <soap12:address location="https://test.example.com/uat/ServicesAccess.asmx" />
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

这是 7.3 及之前版本的输出

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://example.com/webservices/DataServices/v2/ServicesAccess">
  <SOAP-ENV:Header>
    <ns1:AuthenticationHeader>
      <ns1:Username>Foo</ns1:Username>
      <ns1:Password>Bar</ns1:Password>
      <ns1:ClientName>Baz</ns1:ClientName>
    </ns1:AuthenticationHeader>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body>
    <ns1:SubmitWorkItem>
      <ns1:SourceData>
        <ns1:Locations>
          <ns1:Location>
            <ns1:Name>London</ns1:Name>
          </ns1:Location>
          <ns1:Location>
            <ns1:Name>New York</ns1:Name>
          </ns1:Location>
          <ns1:Location>
            <ns1:Name>Paris</ns1:Name>
          </ns1:Location>
          <ns1:Location>
            <ns1:Name>Rome</ns1:Name>
          </ns1:Location>
        </ns1:Locations>
      </ns1:SourceData>
    </ns1:SubmitWorkItem>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

这是 7.4 及更高版本的输出

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://example.com/webservices/DataServices/v2/ServicesAccess">
  <SOAP-ENV:Header>
    <ns1:AuthenticationHeader>
      <ns1:Username>Foo</ns1:Username>
      <ns1:Password>Bar</ns1:Password>
      <ns1:ClientName>Baz</ns1:ClientName>
    </ns1:AuthenticationHeader>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body>
    <ns1:SubmitWorkItem>
      <ns1:SourceData>
        <ns1:Locations/>
      </ns1:SourceData>
    </ns1:SubmitWorkItem>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

您只需应用 1 处更改:

$request = [
    'SourceData' => [
        'any' => new SoapVar($locations->getArrayCopy(), SOAP_ENC_OBJECT, '', '', 'Locations', $namespace)
    ],
 ];
 // add this                           ^--------------^
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 PHP 7.4 中生成 SOAP 数组 的相关文章

  • 无需 cron 在后台发送邮件

    我想知道是否有一种方法可以运行 PHP 循环 以便在后台向订阅者发送几百封电子邮件 我的目标是格式化新闻通讯 单击发送 然后关闭浏览器或更改页面 当然 发送电子邮件的实际过程将在后台运行 不会因浏览器关闭而中断 我知道这可以通过 cron
  • 增加内存限制时出现奇怪的错误

    我使用的是共享托管环境 PHP 的默认内存限制是 32M 我在 Concrete5 设置方面遇到一些问题 当我尝试登录 Concrete5 的管理面板时 出现内存限制错误Allowed memory size of 33554432 byt
  • jquery ajax加载后丢失CSS

    大家知道如何解决 load Ajax 请求后的 css 问题吗 例如 如果我想从网页加载 DIV 在我的 Ajax 请求之后 container load path to div div id 我丢失了与该 div 关联的所有 css 和脚
  • Php 转换 GMT 格式的时间

    我有这个字符串2012 06 27 16 17 06我想将其转换为 GMT 格式 我怎样才能做到这一点 多谢 Use gmdate http php net manual en function gmdate php 使用以下命令将当前日期
  • 从远程托管上的 PHP 获取 PHP 错误日志

    是否有 PHP 函数或其他方式以字符串形式获取 PHP 错误日志 我需要这个 因为我无法访问在其他人的服务器上运行的站点的错误日志 他提出通过电子邮件将错误日志发送给我 但这不太方便 有什么方法可以将错误日志输出到 PHP 页面吗 我意识到
  • 为什么我的浮点数大于 1 时在 MYSQL 中存储为 .9999?

    我将进程时间作为 float 4 4 存储在 MySQL 数据库中 start time microtime TRUE things happen in my script end time microtime TRUE process t
  • 如何使用 PHP 查找字符串中字符的序列模式?

    假设我有随机的文本块 EAMoAAQAABwEBAAAAAAAAAAAAAAABAgMFBgcIBAkBAQABBQEBAAAAAAAAAAAAAAAGAgMEBQcBCBAAAQMDAgMEBQcIBQgGCwEAAQACAxEEBSEG
  • 间歇性 PHP 抽象类错误

    我已经为此奋斗了一段时间 但无法弄清楚 也许其他人也有 或者 Slim PHP Apache 等这里有更深层次的问题 在正常工作几个小时后 我的 Slim 安装将开始给出所有路线均如此 致命错误 类 Slim Collection 包含 1
  • PHP-列出一年中一个月中的所有天[重复]

    这个问题在这里已经有答案了 可能的重复 我在 PHP 中有 2 个日期 如何运行 foreach 循环来遍历所有这些日期 https stackoverflow com questions 3207749 i have 2 dates in
  • 使用 php ping 网站

    我想创建一个 php 脚本 它将 ping 一个域并列出响应时间以及请求的总大小 这将用于监控网站网络 我尝试过curl 这是我到目前为止的代码 function curlTest2 url clearstatcache return if
  • 使用 php 脚本的电子邮件管道

    你好 我想将所有电子邮件 到达我的收件箱 转发到 php 脚本并检索电子邮件内容并将其保存在文件中 因此 我正确地添加了具有管道路径的电子邮件转发器 转发地址 电子邮件受保护 cdn cgi l email protection 管道到程序
  • PHP括号少IF条件不接受多个语句

    我从来都不喜欢控制结构中的括号 直到今天我才意识到它如何只接受括号内的一条语句而不是 if 条件 如果我有多个语句 它会抛出语法错误 这是 PHP 的工作方式还是我的 IDE 有问题 显然错误很明显 但我只是想确保这是正常的 如果您有任何其
  • 为什么 PHPUnit 将一些右大括号显示为未被覆盖?

    我正在使用 PHPUnit 3 6 7 PHP CodeCoverage 1 1 1 和 Xdebug 2 1 2 当我让 PHPUnit 将代码覆盖率统计信息写入 clover 样式的 XML 文件时 它偶尔会显示一个右花括号 表示测试未
  • PHPMailer 验证失败

    当我尝试在工作中使用 Windows Server 2012 上的 PHPMailer 来使用 SMTP 发送报告电子邮件时 出现身份验证失败错误 我在域上使用服务器管理员帐户 我非常确定密码是正确的 检查下面的代码 require PHP
  • Oracle Blob 在 PHP 页面中作为 img src

    我有一个网站当前使用文件服务器上的图像 这些图像显示在页面上 用户可以根据需要拖放每个图像 这是使用 jQuery 完成的 图像包含在列表中 每张图片都非常标准 img src network path image png height 8
  • 访问 Magento 购物车和/或结帐中的运费

    请注意 这个问题是关于运费 而不是价格 有一个重要的区别 即运输方式为店主支付的费用是多少 而不是客户支付的费用 The shipping tablerate数据库表包括一个cost字段 该字段填充在Mage Shipping Model
  • 从关系中合并 Laravel 中的集合

    假设我有 3 张桌子 Images Subject Style 关系是多对多 图像 主题 和多对多 图像 样式 现在我想做一些类似的事情 result subjectResult gt images gt merge styleResult
  • 使用 PHP 将 SVG 图像转换为 PNG

    我正在开发一个网络项目 该项目涉及动态生成的美国地图 根据一组数据为不同的州着色 这个 SVG 文件为我提供了一张很好的美国空白地图 并且很容易更改每个州的颜色 困难在于 IE 浏览器不支持 SVG 因此为了让我使用 svg 提供的便捷语法
  • 简单的颜色变化

    我正在创建一个用户界面 用户可以在其中更改页面的颜色值 我想要的是获取分配给其背景颜色的值并将其变亮一定程度 我只是想获得一条亮点线 而不必每次都制作新图像 示例 用户将背景颜色设置为 ECECEC 现在我希望某个元素边框变成 F4F4F4
  • preg_match 所有以@开头的单词?

    我对正则表达式不太确定 所以我不得不问你 如何用 PHP 判断字符串中是否包含以 开头的单词 例如我有一个像 This is for codeworxx 这样的字符串 我很抱歉 但我没有任何起点 希望你能帮忙 谢谢 萨沙 好的 谢谢你的结果

随机推荐