php5調用web service


工做中須要用php調用web service接口,對php不熟,上網搜搜,發現關於用php調用web service的文章也很少,很多仍是php4裏用nusoap這個模塊調用的方法,其實php5裏已經包含了處理soap的模塊,可是資料太少了,上php官網上查幫助,寫的不是很容易理解,通過屢次實踐,終於搞清楚了,php調用web service仍是很是簡單的。下面用一個例子說明:
php

extension=php_openssl.dllhtml

extension=php_soap.dlljava

php.ini 這2項要開通linux

 

web service服務是一個用java寫的簡單服務,環境爲Tomcat6.0 + Axis2,暴露的方法爲  String hello(String name)web

傳遞一個String參數name,而後返回給客戶端。編程

使用php5開發客戶端:c#

<?phpwindows

header("content-type:text/html;charset=utf-8");api

try {數組

    //$client = new SoapClient("HelloService.wsdl",array('encoding'=>'UTF-8'));

    $client = new SoapClient("http://localhost:8080/axis2/services/HelloService?wsdl",array('encoding'=>'UTF-8'));

  var_dump($client->__getFunctions());

  print("<br/>");

  var_dump($client->__getTypes());

  print("<br/>");

  

 $parm1 = "php client call";

 $param = array('param0' => $parm1);

 $arr = $client->hello($param);

 print_r($arr); 

} catch (SOAPFault $e) {

    print $e;

}

?>

代碼確實很簡單吧,建立SoapClient對象時,可使用保存在本地WSDL文件,也可使用遠程的地址,後面的array數組裏能夠帶上不少的參數,具體參數能夠查php的SoapClient幫助,這裏帶的是字符集編碼,若是調用方法的參數裏有中文,必定要指定字符集編碼,不然會出錯。

調用web service前能夠先調用SoapClient的__geunctions()和__getTypes()方法看一下你要調用的web service暴露的方法,參數和數據類型,須要注意的是傳入的參數名必定要和soapclient裏面定義的一致,不然參數是傳不過去的。(本人在這個上面延誤了很長時間 c#調用不用指定參數名,真奇怪啊)

不知道WSDL的狀況也能夠調用WS,須要使用SoapClient的__soapCall()或__call()方法,具體使用方法能夠查php的幫助文檔。

另外發現個問題,若是web service方法返回的是xml格式的字符串,php接收到之後會本身把數據內容解析出來,而不是xml字符串.

 

 

有個叫Nusoap類,在php4下比較流行。可是淡水此次玩的是php5,因此他就沒戲了。
先惡補一下相關知識。
先要打開php5的web service擴展。linux下,嗯,好像不會-_-!。windows下,把php.ini文件中 extension=php_soap.dll 去掉註釋便可。
方法:
SoapClient->__soapCall()
說明:
class SoapClient {
mixed __soapCall ( string function_name, array arguments [, array options [, mixed input_headers [, array &output_headers]]])
}
In WSDL mode, you can simply call SOAP functions as SoapClient methods. This method useful in non-WSDL mode when soapaction is unknown, uri differs from the default or when sending and/or receiving SOAP Headers
返回值:
一個簡單類型的返回值,或是一個關聯數組
例子:

<?php
 
$client = new SoapClient("some.wsdl");
$client->SomeFunction($a$b$c);
 
$client->__soapCall("SomeFunction",
                     array($a$b$c)
                     );
$client->__soapCall("SomeFunction"
                    array($a$b$c)
                    NULL,
                    new SoapHeader()
                    $output_headers
                    );
 
 
$client = new SoapClient(nullarray('location' =>"http://localhost/soap.php",'uri'=> "http://test-uri/"));
$client->SomeFunction($a$b$c);
$client->__soapCall("SomeFunction"
                    array($a$b$c)
                    );
$client->__soapCall("SomeFunction"
                    array($a$b$c),
                    array('soapaction' => 'some_action','uri' => 'some_uri')
                    );
?>

1.in WSDL mode
soapCall應用web service,例子用的是asp.net的web service,提供service.asmx頁面,調用及查看都比較簡單,手冊上的example也大可能是這個類型,比較簡單.

SOAP發送的協議:

POST /servicepath/service.asmx HTTP/1.1
Host: 211.186.1.4
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: 「http://211.186.5.15/Service/ServiceMethod」

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema"xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <ServiceMethod xmlns="http://211.186.5.15/Service">
      <param1>string</param1>
      <param2>string</param2>
      <param3>string</param3>
    </ServiceMethod>
  </soap:Body>
</soap:Envelope>

調用方法:

<?php
$client = new SoapClient("http://www.xxx.com/service/service.asmx?WSDL");
//向SOAP服務方發送參數值
$param1 = "p1";
$param2 = "p2";
$param3 = "p3";
 
//serviceParam1,serviceParam2,serviceParam3爲發送參數值所對應的參數名(或service端提供的字段名)
$param = array('serviceParam1' => $param1,'serviceParam2' =>$param2,'serviceParam3' => $param3);
 
//默認以parameters字段標示傳遞的參數數組(這裏的web services是.net提供的,因此和php提供的Web service不一樣)
$arr = $client->__soapCall('ServiceMethod',array('parameters' => $param));
//這裏淡水推薦直接使用web services提供的方法,如
//$arr = $client->ServiceMethod($param);
 
print_r($arr);
?>

2.in non-WSDL mode
這種狀況下soapaction is unknown

SOAP發送協議:

POST /services/SoapMethod?WSDL HTTP/1.1
Host: 220.211.1.12:8088
Connection: Keep-Alive
User-Agent: PHP-SOAP/5.2.5
Content-Type: text/xml; charset=utf-8
SOAPAction: 「urn:SoapMethod#ServiceMethod」
Content-Length: 1297

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"xmlns:ns1="urn:SoapMethod" xmlns:xsd="http://www.w3.org/2001/XMLSchema"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="http://220.211.1.12"SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:ServiceMethod>
<ServiceMethodSection xsi:type="ns2:ServiceObjectType">
<param1 xsi:type="xsd:string">01019</param1>
<param2 xsi:type="xsd:long">10</param2>
<param3 xsi:type="xsd:long">0</param3>
<param4 xsi:type="xsd:long">11</param4>
</ServiceMethodSection>
</ns1:ServiceMethod>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

調用方法:

<?php
//傳遞一個參數
try {
      $client = new SoapClient(
                      null,
                      array('location' =>'http://192.168.1.180:8088/services/SoapPage?WSDL','uri' =>'http://192.168.1.180:8088/services/')
                      );    
      $result =  $client->__soapCall('ServiceMethod'array('fieldName' =>"data"))//以數組形式傳遞params 
      //$result =  $client->__soapCall('ServiceMethod', array(new SoapParam("data", 'fieldName')));  //以構造服務端參數的形式構造參數傳遞給服務端  
      var_dump($result);
  } 
  catch (Exception $e) 
  {
      printf("Message = %s",$e->__toString());
  }
?>

附註一下:
class SoapParam {
__construct ( mixed data, string name )
}
參數:
data
The data to pass or return. You can pass this parameter directly as PHP value, but in this case it will be named as paramN and the SOAP Service may not understand it.

name
參數名

<?php
//傳遞多個參數:
//若是服務端在non wsdl的狀況下要求傳遞一個對象參數,該對象中包含多個屬性,則
 
try {
      $client = new SoapClient(
                      null
                      array('location' =>'http://192.168.1.180:8088/services/SoapPage?WSDL','uri' => 'urn:SoapName')
                      );//uri部分也多是uri地址
 
      class Obj{ 
       public $param1 = '01019';
       public $param2 = 10;
       public $param3 = 0;
       public $param4 = 11;
      }
 
    $struct = new Obj();  //建立服務端要求傳遞的對象
    //若是服務端變態到傳遞的參數有的參數類型是你編程語言中沒有的數據類型,
    //如php,沒有Java的Long類型(通常web service考慮通用性,數據類型都是string或int型)
    //就要將參數進行強制類型轉換
    //這樣的處理也只是在SOAP傳輸中將xml的參數類型替換成服務端所要求的類型名
    //並非真實轉化傳遞的數據類型
    $struct->param1 = iconv('gb2312','utf-8',$struct->param1);
    $struct->param2 = new SoapVar($struct->param2,XSD_LONG);
    $struct->param3 = new SoapVar($struct->param3,XSD_LONG);
    $struct->param4 = new SoapVar($struct->param4,XSD_LONG);
 
    //序列化對象中使用SoapVar的方法參考php手冊對SoapVar的解釋,每一個參數都解釋的很清楚
    $soapstruct = new SoapVar($structSOAP_ENC_OBJECT"ServiceObjectType","http://soapinterop.org/xsd")//對象序列化,注意區分,SOAP對象的序列化不是用serialize
    
      $result =  $client-> ServiceMethod(new SoapParam($soapstruct,'ServiceMethodSection'));      //$result =  $client->__soapCall('ServiceMethod', array(new SoapParam($soapstruct, 'ServiceMethodSection')));           var_dump($result);  } catch (Exception $e) {      printf("Message = %s",$e->__toString());  }

?>

相關文章
相關標籤/搜索