如何创建SoapParams的PHP SoapParam?

时间:2012-10-04 13:29:09

标签: php soap-client

我正在使用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>

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

1 个答案:

答案 0 :(得分:6)

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

请求的这一部分:

...
<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>
...

必须转换为Object(Struct):

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的一个实例。