PHP的SOAP擴展可以用來提供和使用
Web services。換句話說,PHP開發者可以利用這個PHP擴展來寫他們自己的Web services,也可以寫一些客戶端來使用給定的Web services。
PHP5中的這個SOAP擴展目的是為了實現PHP對
Web services的支持。與其它實現PHP對Web services的支持的方法不同,SOAP擴展是用C寫的,因此它比其它方法具有速度優勢。
SOAP擴展支持以下規范。
* SOAP 1.1
* SOAP 1.2
* WSDL 1.1
SOAP擴展主要用來處理RPC形式的
Web services。不過,你也可以使用文本形式的WSDL文件配合WSDL模式的服務端和客戶端。
這個擴展使用 GNOME XML庫來處理XML。
擴展中的類
這個擴展實現了6個類。其中有三個高級的類,它們的方法很有用,它們是 SoapClient,SoapServer和SoapFault。另外三個類除了構造器外沒有其它別的方法,這三個是低級的類,它們是SoapHeader,SoapParam和SoapVar。
SoapClient類
這個類用來使用Web services。SoapClient類可以作為給定Web services的客戶端。
它有兩種操作形式:
* WSDL 模式
* Non-WSDL 模式
在WSDL模式中,構造器可以使用WSDL文件名作為參數,并從WSDL中提取服務所使用的信息。
non-WSDL模式中使用參數來傳遞要使用的信息。這個類有許多可以用來使用服務的有用的方法。其中SoapClient::__soapCall()是最重要的。這個方法可以用來調用服務中的某個操作。
SoapServer類
這個類可以用來提供Web services。
與SoapClient類似,SoapServer也有兩種操作模式:WSDL模式和non-WSDL模式。這兩種模式的意義跟
SoapClient的兩種模式一樣。在WSDL模式中,服務實現了WSDL提供的接口;在non-WSDL模式中,參數被用來管理服務的行為。
在SoapServer類的眾多方法中,有三個方法比較重要。它們是SoapServer::setClass(),SoapServer::addFunction()和SoapServer::handle()。
SoapServer::setClass()方法設定用來實現Web Service的類。SoapServer::setClass所設定的類中的所有公共方法將成為Web Services的操作(operation)。
SoapServer::addFunction()方法用來添加一個或多個作為Web Services操作(operation)的函數。
SoapServer:: handle()方法指示Web
Service腳本開始處理進入的請求。Web
Service腳本是用PHP腳本寫的一個或多個SoapServer對象的實例。盡管你可以有不止一個的SoapServer對象,但通常的習慣是一個
腳本只擁有一個SoapServer實例。在調用SoapServer::handle()方法之前,Web
Service腳本會使用設置在SoapServer對象實例上的任何信息來處理進入的請求和輸出的相應。
SoapFault類
這個類從Exception類繼承而來,可以用來處理錯誤。SoapFault實例可以拋出或獲取Soap錯誤的相關信息并按程序員的請求處理。
SoapHeader類
這個類可以用來描述SOAP headers。它只是一個只包含構造器方法的數據容器。
SoapParam類
SoapParam也是一個只包含構造器方法的數據容器。這個方法可以用來描述傳遞給Web services操作的參數。在non-WSDL模式中這是一個很有用的類,可以用來傳遞所期望格式的參數信息。
SoapVar類
SoapVar也是一個只包含構造器的低級類,與SoapHeader和SoapParam類相似。這個類可以用來給一個Web services操作傳遞編碼參數。這個類對non-WSDL中傳遞類型信息是非常有用的。
WSDL VS. non-WSDL模式
Web Services有兩種實現模式:契約先行(Contract first)模式和代碼先行(Code first)模式。
契約先行模式使用了一個用XML定義的服務接口的WSDL文件。WSDL文件定義了服務必須實現或客戶端必須使用的接口。SoapServer和SoapClient的WSDL模式就基于這個概念。
在
代碼先行模式中,首先要先寫出實現服務的代碼。然后在大多數情況下,代碼會產生一個契約,換種說法,一個WSDL。接著客戶端在使用服務的時候就可以使用
那個WSDL來獲得服務的接口。盡管如此,PHP5的擴展并沒有從代碼輸出一個WSDL的規定,考慮到這種情況,可以在non-WSDL模式下使用
SoapServer和SoapClient。
SOAP擴展與Hello World
這一節介紹如何使用WSDL模式和non-WSDL模式來實現服務和客戶端。相對而言,使用WSDL模式來實現服務和客戶端會比較容易,假定已經有一個定義了接口的WSDL文件。因此這一節會先介紹如何使用WSDL模式實現一個Web Service。
在這個Hello World例子的服務中有一個被命名為greet的操作。這個操作有一個字符串形式的名字并返回一個字符串形式的greeting。所用到的WSDL如下:
<wsdl:definitions
xmlns:impl='http://wso2.org/wsf/php/helloService'
xmlns:intf='http://wso2.org/wsf/php/helloService'
xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'
xmlns:wsdlsoap='http://schemas.xmlsoap.org/wsdl/soap/'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
targetNamespace='http://wso2.org/wsf/php/helloService'>
<wsdl:types>
<schema elementFormDefault='qualified'
xmlns:impl='http://wso2.org/wsf/php/helloService'
xmlns:intf='http://wso2.org/wsf/php/helloService'
xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace='http://wso2.org/wsf/php/helloService' >
<element name='greet'>
<complexType>
<sequence>
<element name='name' type='xsd:string' />
</sequence>
</complexType>
</element>
<element name='greetResponse'>
<complexType>
<sequence>
<element name='greetReturn' type='xsd:string' />
</sequence>
</complexType>
</element>
</schema>
</wsdl:types>
<wsdl:message name='greetRequest'>
<wsdl:part name='parameters' element='impl:greet' />
</wsdl:message>
<wsdl:message name='greetResponse'>
<wsdl:part name='parameters' element='impl:greetResponse' />
</wsdl:message>
<wsdl:portType name='helloService'>
<wsdl:operation name='greet'>
<wsdl:input name='greetRequest' message='impl:greetRequest' />
<wsdl:output name='greetResponse' message='impl:greetResponse' />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name='helloServiceSoapBinding' type='impl:helloService'>
<wsdlsoap:binding transport='http://schemas.xmlsoap.org/soap/http' style='document' />
<wsdl:operation name='greet'>
<wsdlsoap:operation soapAction='helloService#greet' />
<wsdl:input name='greetRequest'>
<wsdlsoap:body use='literal' />
</wsdl:input>
<wsdl:output name='greetResponse'>
<wsdlsoap:body use='literal' />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name='helloService'>
<wsdl:port binding='impl:helloServiceSoapBinding' name='helloService'>
<wsdlsoap:address location='http://localhost/hello/hello_service_wsdl.php' />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
WSDL模式服務
下面是WSDL模式的服務所使用的SOAP擴展API代碼:
<?php
function greet($param) {
$retval = 'Hello '.$param->name;
$result = array('greetReturn' => $retval);
return $result;
}
$server = new SoapServer('hello.wsdl');
$server->addFunction('greet');
$server->handle();
?>
在這個服務的實現過程中,函數實現了WSDL所定義的服務操作greet,greet操作有一個WSDL指定的參數,按照greet操作的語義,這個參數是一個用戶的名字。最后handle調用了觸發處理請求的服務對象。
WSDL模式客戶端
客戶端代碼如下
<?php
try {
$client = new SoapClient('hello.wsdl');
$result = $client->__soapCall('greet', array(array('name' => 'Sam')));
printf("Result = %s", $result->greetReturn);
} catch (Exception $e) {
printf("Message = %s",$e->__toString());
}
?>
客戶端代碼中,首先創建一個使用WSDL文件作參數的SoapClient實例。接著__soapCall()調用作為參數傳入它的操作,也就是greet和傳入操作的參數。
請求和響應
當你將上述的PHP腳本放在你web服務器目錄下的文檔中,并利用WEB瀏覽器或在PHP解析器的命令行調用腳本,客戶端發送一個SOAP請求到服務端腳本,服務端將向客戶端發送一個SOAP響應來響應客戶端的請求。
下面是客戶端所發送的SOAP請求:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://wso2.org/wsf/php/helloService">
<SOAP-ENV:Body>
<ns1:greet>
<ns1:name>Sam</ns1:name>
</ns1:greet>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
下面是服務端響應上訴請求而發送的SOAP響應:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://wso2.org/wsf/php/helloService">
<SOAP-ENV:Body>
<ns1:greetResponse>
<ns1:greetReturn>Hello Sam</ns1:greetReturn>
</ns1:greetResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
上面的SOAP消息都是利用WSDL模式的服務端和客戶端來獲取的。也可以利用non-WSDL模式的服務端和客戶端來產生與上面相同的SOAP消息。但是,PHP代碼必須有一點改變。下一節會說明如何使用non-WSDL模式。
non-WSDL模式服務端
<?php
function greet($param) {
$retval = 'Hello '.$param;
return new SoapParam($retval, 'greetReturn');
}
$server = new SoapServer(null, array('uri' => 'http://wso2.org/wsf/php/helloService'));
$server->addFunction('greet');
$server->handle();
?>
在non
-WSDL模式中,想WSDL模式一樣首先實現greet函數的功能,但是函數實現的方式跟WSDL模式稍稍有所不同。在non-WSDL模式中,我們必
須返回一個SoapParam對象作為響應,而不是一個數組。創建服務時,第一個參數設為null,說明沒有提供WSDL;接著傳遞一個選項作為參數,這
個選項參數是服務的URI。最后像WSDL模式一樣調用剩下的方法。
non-WSDL模式客戶端
<?php
try {
$client = new SoapClient(null,
array('location' => 'http://localhost/hello/hello_service_nonwsdl.php',
'uri' => 'http://wso2.org/wsf/php/helloService'));
$result = $client->__soapCall('greet', array(new SoapParam('Sam', 'name'))); printf("Result = %s", $result);
} catch (Exception $e) {
printf("Message = %s",$e->__toString());
}
?>
在non-WSDL模式中,因為沒有使用WSDL,傳遞了一個包含服務所在位置和服務URI的參數數組作為參數。然后象WSDL模式中一樣調用__soapCall()方法,但是使用了SoapParam類用指定格式打包參數。返回的結果將獲取greet中的響應。
相關文章:
PHP代碼的優與劣
如何用PHP和mysql創建一個ShoutBox
PHP的文件包含
PHP的正則表達式處理函數總結分析
PHP文件上傳實例詳解
結論
這篇文章介紹了SOAP擴展,可以在PHP中通過它來提供和使用Web
Services。PHP擴展的強項是它的簡單和快速。使用C寫的SOAP擴展來運行服務端和客戶端是非常簡單的。雖然SOAP擴展在處理一些簡單的
Web Services時很有用,但是當用它來處理所有的Web Services時就表現出它的局限性。 WSO
WSF/PHP就是為了彌補PHP擴展的缺陷而開發的,它是開源的,可以實現SOAP類似的功能并且支持MTOM,WS-Addressing,WS-
Security和WS-RelaiableMessaging。WSO2 WSF/PHP
支持與SOAP擴展類似的API。我們正計劃將API打包起來提供跟SOAP擴展一樣的API,會用C來寫。
posted on 2008-12-21 09:19
墻頭草 閱讀(3537)
評論(0) 編輯 收藏 所屬分類:
PHP