我正在使用SoapClient与http://weather.gov/forecasts/xml/SOAP_server/ndfdXMLserver.php?wsdl进行交互 并调用NDFDgenByDay()工作正常,没有问题,但是当我想调用NDFDgen()时我必须使用相反,因为我无法弄清楚如何在使用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'
)
);
Run Code Online (Sandbox Code Playgroud)
我得到的错误是:
Fatal error: Uncaught SoapFault exception: [Client] SOAP-ERROR: Encoding: object has no 'maxt' property in [Redacted]\data\WeatherService.php:199
Run Code Online (Sandbox Code Playgroud)
这是通过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>
Run Code Online (Sandbox Code Playgroud)
所以基本上,我想使用SoapClient进行所有Soap交互,但我不知道如何做复杂的参数,如上面的weatherParameters参数,如果在使用SoapClient时可以指定weatherParameters,请告诉我如何,因为替代方案,使用curl,在我的php中添加超过100行代码,在制作soap信封并初始化和使用curl之间,然后从响应信封中解析响应xml.
好的,我找到了解决方案.
这部分请求:
...
<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>
...
Run Code Online (Sandbox Code Playgroud)
必须转换为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;
}
}
Run Code Online (Sandbox Code Playgroud)
我对值进行了硬编码,但如果需要,您可以使值动态化.然后我实例化结构:
$wParameters = new weatherParameters();
Run Code Online (Sandbox Code Playgroud)
然后我告诉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'
);
Run Code Online (Sandbox Code Playgroud)
然后将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')
);
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,我必须阅读所有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文档中有7个SoapVar的提及/链接,但没有一个指出当你需要SoapParam来表示复杂对象时,SoapParam的参数1将是SoapVar的一个实例.