【问题标题】:How to structure complex nested soap parameters如何构造复杂的嵌套soap参数
【发布时间】:2014-01-15 23:29:19
【问题描述】:

好吧,这个问题把我逼疯了。我没有成功尝试使用 PHP 和 SOAP 连接到 Web 服务。我不知道出了什么问题,而且这是一项全新的服务,而且他们的“文档”很差。所以我不知道问题是否真的出在他们的最后,但我没有足够的 SOAP 经验来确定这一点。我祈祷有人可以帮助我。

我已经能够通过将 XML 直接放入 SOAP UI 来连接到服务,但是每当我尝试使用 SoapClient 时,它就会崩溃。我要发送的 XML 结构看起来像

<Envelope xmlns:ns1="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://a.uri" xmlns:ns3="http://tempuri.org/">
 <Body>
    <GetAuthorization>
        <ns1:registrationObj ns1:type="ns2:RegistrationAuthorization">
            <ns2:Company>####</ns2:Company>
            <ns2:Computer>####</ns2:Computer>
            <ns2:Facility>####</ns2:Facility>
        </ns1:registrationObj> 
    </GetAuthorization>
</Body>
</Envelope>

我尝试过的方法太多了,无法一一列举。使用 __soapCall、$client->method()、SoapVar 和 SoapParam。总的来说,我发现 PHP 的 SoapClient 的文档有点稀疏。但我什至无法让调用的结构与我想要的匹配(通过 __getLastRequest() 转储)

我注意到的一件事是客户端不断删除我的数组的第一个元素(在那些实例上,当我尝试将参数作为普通数组传递时。所以:

$params = array("Company" => "abc",
                "Computer" => "def",
                "Facility" => "ghi");
$result = $soap_client->__soapCall('GetAuthorization',$params);

返回

<env:Body>
    <ns1:GetAuthorization/>
    <param1>def</param1>
    <param2>ghi</param2>
</env:Body>

请注意在这种情况下 GetAuthorization 如何自行关闭并删除第一个数组元素。我也分别经历过这两种情况(值得注意的是,我已经正确命名了参数。我经历了很多次迭代,我不记得什么尝试产生了哪些结果。尽管如此,SOAP 的行为并不像我希望它会。它无法正确封装数据和/或丢弃随机元素。

$parameters = 
array("ra" => new SoapVar(array(
    "CompanyId" => new SoapVar("####", SOAP_ENC_OBJECT, 'guid', 'http://schemas.microsoft.com/2003/10/Serialization/', 'CompanyId', 'http://schemas.datacontract.org/x/y/z.xx'),
    "ComputerId" => new SoapVar("{####}", SOAP_ENC_OBJECT, 'string', 'http://www.w3.org/2001/XMLSchema', 'ComputerId', 'http://schemas.datacontract.org/x/y/z.xx'),
    "FacilityId" => new SoapVar("####", SOAP_ENC_OBJECT, 'guid', 'http://schemas.microsoft.com/2003/10/Serialization/', 'FacilityId', 'http://schemas.datacontract.org/x/y/z.xx')
), SOAP_ENC_OBJECT, 'RegistrationAuthorization', 'http://schemas.datacontract.org/x/y/z.xx', 'ra', "http://schemas.datacontract.org/x/y/z.xx"

)));

$result = $auth_client->GetAuthorization($parameters);

是我最初试图推动的结构(在我简化它以试图找出问题之前),因为我需要对我需要的参数的命名空间进行如此多的控制。但是,这只是使用自闭元素发出请求。

有人可以告诉我如何构造调用以产生适当的 XML 结构吗?这可能是在服务端并且 WSDL 有问题吗? (我不确定 WSDL 在后端到底负责什么。)

对于这个问题含糊不清,我深表歉意,但我感到很迷茫,我什至不确定该问哪个合适的人。 :-(

【问题讨论】:

  • __getFunctions() 告诉您有关此方法的哪些内容,也许还发布了在那里使用的__getTypes() 的相关部分? (或者,就此而言:如果 wsdl 是公开的 / 不需要保密,也许可以分享那个 ..)
  • 不幸的是,WSDL 和相关信息是保密的 :-(。我真的很想包括它。
  • 啊,好吧,那么:没有函数和参数的定义,第一个示例看起来确实应该可以工作...您使用的是内置的香草SoapClient,还是其他一些一个或一个扩展/改变它?
  • 我正在使用内置的 SOAP 客户端。抱歉,我是 SOAP 调用的新手,不熟悉 WSDL 的确切功能。服务端是否可能出现错误?他们的代码会影响我的 SOAP 客户端如何构建请求吗?该服务是全新的,我是第一个尝试使用它的人。
  • 这不是服务器主动可以更改的(毕竟这是您设置的请求并需要发送到服务器)。 但是一个错误/错误的wsdl 可能会产生奇怪的后果。然而,再看一遍:在你的第一个例子中,你可以试试$soap_client-&gt;__soapCall('GetAuthorization',array($params)); 吗? (所以在数组中增加了一层步骤。似乎应该这样做。要么是$client-&gt;FunctionName($parameter),要么是$client-&gt;__soapCall('FunctionName',array($parameter)),看到区别了吗?

标签: php soap


【解决方案1】:

它应该可以工作:

<?php
$client = new \SoapClient(null, array(
    'uri'           => 'http://localhost/stack/21150482/',
    'location'      => 'http://localhost/stack/21150482/server.php',
    'trace'         => true
));
try {

    $company         = new \SoapVar('XXXXX', XSD_STRING, null, null, 'Company', 'http://a.uri');
    $computer        = new \SoapVar('XXXXX', XSD_STRING, null, null, 'Computer', 'http://a.uri');
    $facility        = new \SoapVar('XXXXX', XSD_STRING, null, null, 'Facility', 'http://a.uri');

    $registrationObj = new \SoapVar(
        array($company,$computer,$facility),
        SOAP_ENC_OBJECT,
        'RegistrationAuthorization',
        'http://a.uri',
        'registrationObj',
        'http://www.w3.org/2001/XMLSchema-instance'
    );

    $client->GetAuthorization($registrationObj);

} catch (\Exception $e) {
    var_dump($e->getMessage());
}

$dom = new DOMDocument();
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($client->__getLastRequest());

print '<pre>';
print htmlspecialchars($dom->saveXML());

我的结果是:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://localhost/stack/21150482/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://a.uri" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
    <ns1:GetAuthorization>
      <xsi:registrationObj xsi:type="ns2:RegistrationAuthorization">
        <ns2:Company xsi:type="xsd:string">XXXXX</ns2:Company>
        <ns2:Computer xsi:type="xsd:string">XXXXX</ns2:Computer>
        <ns2:Facility xsi:type="xsd:string">XXXXX</ns2:Facility>
      </xsi:registrationObj>
    </ns1:GetAuthorization>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

【讨论】:

  • 这应该被标记为答案。绝对帮助我摆脱了困境,+1。
【解决方案2】:

我使用的不同方法是:

<?php 

//note the "(object)" casting
$params = (object)[
  'registrationObj' => (object)[
    'Company' => 'abc',
    'Computer' => 'def',
    'Facility' => 'ghi'
  ]
];

$soap_client = new SoapClient('localhost/soap');

//direct call of the method GetAuthorization (without __soapCall)
$return = $soap_client->GetAuthorization($params);

应该适用于 PHP >= 5.4

【讨论】:

    猜你喜欢
    • 2018-05-15
    • 1970-01-01
    • 1970-01-01
    • 2019-06-06
    • 2023-04-03
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多