4

我正在使用 SoapClient 与http://weather.gov/forecasts/xml/SOAP_server/ndfdXMLserver.php?wsdl交互 并调用 NDFDgenByDay() 工作正常,没有问题,但是当我想调用 NDFDgen() 我必须使用curl 而是因为我不知道在使用 SoapClient 时如何将 weatherParameters 传递给 NDFDgen()。这是我尝试过的:

...
$this->client =
    new SoapClient(
        'http://weather.gov/forecasts/xml/SOAP_server/ndfdXMLserver.php?wsdl',
        array('cache_wsdl'=>WSDL_CACHE_NONE)
    );
...
$this->xml =
    $this->client->NDFDgen(
        new SoapParam($this->latitude,  'latitude'),
        new SoapParam($this->longitude,'longitude'),
        new SoapParam('time-series',   'product'),
        new SoapParam($startTime,       'startTime'),
        new SoapParam($endTime,     'startTime'),
        new SoapParam('e',             'Unit'),
        new SoapParam(
            array(
                new SoapParam(false,'maxt'),        new SoapParam(false,'mint'),
                new SoapParam(true, 'temp'),        new SoapParam(true, 'dew'),
                new SoapParam(true, 'pop12'),       new SoapParam(true, 'qpf'),
                new SoapParam(true, 'sky'),         new SoapParam(true, 'snow'),
                new SoapParam(true, 'wspd'),        new SoapParam(true, 'wdir'),        //10
                new SoapParam(false,'wx'),          new SoapParam(false,'waveh'),
                new SoapParam(true, 'icons'),       new SoapParam(true, 'rh'),
                new SoapParam(true, 'appt'),        new SoapParam(false,'incw34'),
                new SoapParam(false,'incw50'),      new SoapParam(false,'incw64'),
                new SoapParam(false,'cumw34'),      new SoapParam(false,'cumw50'),      //20
                new SoapParam(false,'cumw64'),      new SoapParam(false,'critfireo'),
                new SoapParam(false,'dryfireo'),    new SoapParam(false,'conhazo'),
                new SoapParam(false,'ptornado'),    new SoapParam(false,'phail'),
                new SoapParam(false,'ptstmwinds'),  new SoapParam(false,'pxtornado'),
                new SoapParam(false,'pxhail'),      new SoapParam(false,'pxtstmwinds'), //30
                new SoapParam(false,'ptotsvrtstm'), new SoapParam(false,'pxtotsvrtstm'),
                new SoapParam(false,'tmpabv14d'),   new SoapParam(false,'tmpblw14d'),
                new SoapParam(false,'tmpabv30d'),   new SoapParam(false,'tmpblw30d'),
                new SoapParam(false,'tmpabv90d'),   new SoapParam(false,'tmpblw90d'),
                new SoapParam(false,'prcpabv14d'),  new SoapParam(false,'prcpblw14d'),  //40
                new SoapParam(false,'prcpabv30d'),  new SoapParam(false,'prcpblw30d'),
                new SoapParam(false,'prcpabv90d'),  new SoapParam(false,'prcpblw90d'),
                new SoapParam(true, 'precipa_r'),   new SoapParam(true, 'sky_r'),
                new SoapParam(true, 'temp_r'),      new SoapParam(true, 'td_r'),
                new SoapParam(true, 'wdir_r'),      new SoapParam(true, 'wspd_r'),      //50
                new SoapParam(true, 'wwa'),         new SoapParam(true, 'wgust')
            ),
            'weatherParameters'
        )
    ); 

我得到的错误是:

Fatal error: Uncaught SoapFault exception: [Client] SOAP-ERROR: Encoding: object has no 'maxt' property in [Redacted]\data\WeatherService.php:199

这是通过 curl 工作的 xml:

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ndf="http://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl">
   <soapenv:Header/>
   <soapenv:Body>
      <ndf:NDFDgen soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <latitude xsi:type="xsd:decimal">{$this->latitude}</latitude>
         <longitude xsi:type="xsd:decimal">{$this->longitude}</longitude>
         <product xsi:type="xsd:string">time-series</product>
         <startTime xsi:type="xsd:dateTime">{$this->startTime}</startTime>
         <endTime xsi:type="xsd:dateTime">{$this->endTime}</endTime>
         <Unit xsi:type="xsd:string">e</Unit>
         <weatherParameters xsi:type="ndf:weatherParametersType">
            <!--You may enter the following 52 items in any order-->
            <maxt xsi:type="xsd:boolean">false</maxt>
            <mint xsi:type="xsd:boolean">false</mint>
            <temp xsi:type="xsd:boolean">true</temp>
            <dew xsi:type="xsd:boolean">true</dew>
            <pop12 xsi:type="xsd:boolean">true</pop12>
            <qpf xsi:type="xsd:boolean">true</qpf>
            <sky xsi:type="xsd:boolean">true</sky>
            <snow xsi:type="xsd:boolean">true</snow>
            <wspd xsi:type="xsd:boolean">true</wspd>
            <wdir xsi:type="xsd:boolean">true</wdir>
            <wx xsi:type="xsd:boolean">false</wx>
            <waveh xsi:type="xsd:boolean">false</waveh>
            <icons xsi:type="xsd:boolean">true</icons>
            <rh xsi:type="xsd:boolean">true</rh>
            <appt xsi:type="xsd:boolean">true</appt>
            <incw34 xsi:type="xsd:boolean">false</incw34>
            <incw50 xsi:type="xsd:boolean">false</incw50>
            <incw64 xsi:type="xsd:boolean">false</incw64>
            <cumw34 xsi:type="xsd:boolean">false</cumw34>
            <cumw50 xsi:type="xsd:boolean">false</cumw50>
            <cumw64 xsi:type="xsd:boolean">false</cumw64>
            <critfireo xsi:type="xsd:boolean">false</critfireo>
            <dryfireo xsi:type="xsd:boolean">false</dryfireo>
            <conhazo xsi:type="xsd:boolean">false</conhazo>
            <ptornado xsi:type="xsd:boolean">false</ptornado>
            <phail xsi:type="xsd:boolean">false</phail>
            <ptstmwinds xsi:type="xsd:boolean">false</ptstmwinds>
            <pxtornado xsi:type="xsd:boolean">false</pxtornado>
            <pxhail xsi:type="xsd:boolean">false</pxhail>
            <pxtstmwinds xsi:type="xsd:boolean">false</pxtstmwinds>
            <ptotsvrtstm xsi:type="xsd:boolean">false</ptotsvrtstm>
            <pxtotsvrtstm xsi:type="xsd:boolean">false</pxtotsvrtstm>
            <tmpabv14d xsi:type="xsd:boolean">false</tmpabv14d>
            <tmpblw14d xsi:type="xsd:boolean">false</tmpblw14d>
            <tmpabv30d xsi:type="xsd:boolean">false</tmpabv30d>
            <tmpblw30d xsi:type="xsd:boolean">false</tmpblw30d>
            <tmpabv90d xsi:type="xsd:boolean">false</tmpabv90d>
            <tmpblw90d xsi:type="xsd:boolean">false</tmpblw90d>
            <prcpabv14d xsi:type="xsd:boolean">false</prcpabv14d>
            <prcpblw14d xsi:type="xsd:boolean">false</prcpblw14d>
            <prcpabv30d xsi:type="xsd:boolean">false</prcpabv30d>
            <prcpblw30d xsi:type="xsd:boolean">false</prcpblw30d>
            <prcpabv90d xsi:type="xsd:boolean">false</prcpabv90d>
            <prcpblw90d xsi:type="xsd:boolean">false</prcpblw90d>
            <precipa_r xsi:type="xsd:boolean">true</precipa_r>
            <sky_r xsi:type="xsd:boolean">true</sky_r>
            <temp_r xsi:type="xsd:boolean">true</temp_r>
            <td_r xsi:type="xsd:boolean">true</td_r>
            <wdir_r xsi:type="xsd:boolean">true</wdir_r>
            <wspd_r xsi:type="xsd:boolean">true</wspd_r>
            <wwa xsi:type="xsd:boolean">true</wwa>
            <wgust xsi:type="xsd:boolean">true</wgust>
         </weatherParameters>
      </ndf:NDFDgen>
    </soapenv:Body>
</soapenv:Envelope>

所以基本上,我想对所有的Soap交互使用SoapClient,但是我不知道如何做复杂的参数,比如上面的weatherParameters参数,如果在使用SoapClient时可以指定weatherParameters,请告诉我如何,因为替代方案,使用 curl,实际上在我的 php 中添加了超过 100 行额外的代码,在制作肥皂信封和初始化和使用 curl 之间,然后从响应信封中解析出响应 xml。

4

1 回答 1

7

好的,我找到了解决方案。

这部分请求:

...
<weatherParameters xsi:type="ndf:weatherParametersType">
    <!--You may enter the following 52 items in any order-->
    <maxt xsi:type="xsd:boolean">false</maxt>
    <mint xsi:type="xsd:boolean">false</mint>
    <temp xsi:type="xsd:boolean">true</temp>
    <dew xsi:type="xsd:boolean">true</dew>
    <pop12 xsi:type="xsd:boolean">true</pop12>
    <qpf xsi:type="xsd:boolean">true</qpf>
    <sky xsi:type="xsd:boolean">true</sky>
    <snow xsi:type="xsd:boolean">true</snow>
    <wspd xsi:type="xsd:boolean">true</wspd>
    <wdir xsi:type="xsd:boolean">true</wdir>
    <wx xsi:type="xsd:boolean">false</wx>
    <waveh xsi:type="xsd:boolean">false</waveh>
    <icons xsi:type="xsd:boolean">true</icons>
    <rh xsi:type="xsd:boolean">true</rh>
    <appt xsi:type="xsd:boolean">true</appt>
    <incw34 xsi:type="xsd:boolean">false</incw34>
    <incw50 xsi:type="xsd:boolean">false</incw50>
    <incw64 xsi:type="xsd:boolean">false</incw64>
    <cumw34 xsi:type="xsd:boolean">false</cumw34>
    <cumw50 xsi:type="xsd:boolean">false</cumw50>
    <cumw64 xsi:type="xsd:boolean">false</cumw64>
    <critfireo xsi:type="xsd:boolean">false</critfireo>
    <dryfireo xsi:type="xsd:boolean">false</dryfireo>
    <conhazo xsi:type="xsd:boolean">false</conhazo>
    <ptornado xsi:type="xsd:boolean">false</ptornado>
    <phail xsi:type="xsd:boolean">false</phail>
    <ptstmwinds xsi:type="xsd:boolean">false</ptstmwinds>
    <pxtornado xsi:type="xsd:boolean">false</pxtornado>
    <pxhail xsi:type="xsd:boolean">false</pxhail>
    <pxtstmwinds xsi:type="xsd:boolean">false</pxtstmwinds>
    <ptotsvrtstm xsi:type="xsd:boolean">false</ptotsvrtstm>
    <pxtotsvrtstm xsi:type="xsd:boolean">false</pxtotsvrtstm>
    <tmpabv14d xsi:type="xsd:boolean">false</tmpabv14d>
    <tmpblw14d xsi:type="xsd:boolean">false</tmpblw14d>
    <tmpabv30d xsi:type="xsd:boolean">false</tmpabv30d>
    <tmpblw30d xsi:type="xsd:boolean">false</tmpblw30d>
    <tmpabv90d xsi:type="xsd:boolean">false</tmpabv90d>
    <tmpblw90d xsi:type="xsd:boolean">false</tmpblw90d>
    <prcpabv14d xsi:type="xsd:boolean">false</prcpabv14d>
    <prcpblw14d xsi:type="xsd:boolean">false</prcpblw14d>
    <prcpabv30d xsi:type="xsd:boolean">false</prcpabv30d>
    <prcpblw30d xsi:type="xsd:boolean">false</prcpblw30d>
    <prcpabv90d xsi:type="xsd:boolean">false</prcpabv90d>
    <prcpblw90d xsi:type="xsd:boolean">false</prcpblw90d>
    <precipa_r xsi:type="xsd:boolean">true</precipa_r>
    <sky_r xsi:type="xsd:boolean">true</sky_r>
    <temp_r xsi:type="xsd:boolean">true</temp_r>
    <td_r xsi:type="xsd:boolean">true</td_r>
    <wdir_r xsi:type="xsd:boolean">true</wdir_r>
    <wspd_r xsi:type="xsd:boolean">true</wspd_r>
    <wwa xsi:type="xsd:boolean">true</wwa>
    <wgust xsi:type="xsd:boolean">true</wgust>
</weatherParameters>
...

必须转换为对象(结构):

class weatherParameters {
    function weatherParameters() {
        $this->maxt     = false;    $this->mint     = false;
        $this->temp     = true;     $this->dew          = true;
        $this->pop12        = true;     $this->qpf          = true;
        $this->sky          = true;     $this->snow     = true;
        $this->wspd     = true;     $this->wdir     = true;
        $this->wx           = false;    $this->waveh        = false;
        $this->icons        = true;     $this->rh           = true;
        $this->appt     = true;     $this->incw34       = false;
        $this->incw50       = false;    $this->incw64       = false;
        $this->cumw34       = false;    $this->cumw50       = false;
        $this->cumw64       = false;    $this->critfireo    = false;
        $this->dryfireo = false;    $this->conhazo      = false;
        $this->ptornado = false;    $this->phail        = false;
        $this->ptstmwinds   = false;    $this->pxtornado    = false;
        $this->pxhail       = false;    $this->pxtstmwinds  = false;
        $this->ptotsvrtstm  = false;    $this->pxtotsvrtstm= false;
        $this->tmpabv14d    = false;    $this->tmpblw14d    = false;
        $this->tmpabv30d    = false;    $this->tmpblw30d    = false;
        $this->tmpabv90d    = false;    $this->tmpblw90d    = false;
        $this->prcpabv14d   = false;    $this->prcpblw14d   = false;
        $this->prcpabv30d   = false;    $this->prcpblw30d   = false;
        $this->prcpabv90d   = false;    $this->prcpblw90d   = false;
        $this->precipa_r    = true;     $this->sky_r        = true;
        $this->temp_r       = true;     $this->td_r     = true;
        $this->wdir_r       = true;     $this->wspd_r       = true;
        $this->wwa          = true;     $this->wgust        = true;
    }
}

我对这些值进行了硬编码,但如果需要,您可以使这些值动态化。然后我实例化结构:

$wParameters = new weatherParameters();

然后我告诉 SoapClient 如何将该对象转换为 XML 片段:

$weatherParameters = new SoapVar(
    // object to convert,encoding,name to give the object, name space definition
    $wParameters, SOAP_ENC_OBJECT, 'weatherParameters', 'http://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl'
);

然后将 SoapVar 作为 SoapParam 传递给函数调用:

$this->xml =
    $this->client->NDFDgen(
        new SoapParam($this->latitude,  'latitude'),
        new SoapParam($this->longitude,'longitude'),
        new SoapParam('time-series',   'product'),
        new SoapParam($startTime,       'startTime'),
        new SoapParam($endTime,     'startTime'),
        new SoapParam('e',             'Unit'),
        new SoapParam($weatherParameters,'weatherParameters')
    );

所以要弄清楚这一点,我必须阅读所有 PHP Soap... 文档,然后当我阅读 SoapVar http://php.net/manual/en/class.soapvar.php上的文档时,示例SoapVar 展示了它是如何与 SoapParam 一起使用的,我认为 SoapParam http://php.net/manual/en/soapparam.soapparam.php中的示例也应该更好地说明 SoapVar 和 SoapParam 之间的关系,否则,您可能无法理解你需要一个 SoapVar 来创建一个复杂的 SoapParam。SoapParam doc 中有 7 个 SoapVar 提及/链接,但没有一个指出当您需要 SoapParam 表示复杂对象时,SoapParam 的参数 1 将是 SoapVar 的一个实例。

于 2012-10-04T14:53:35.177 回答