它是一個開源軟件,是完全采用PHP語言編寫的、通過HTTP收發SOAP消息的一系列PHP類,由NuSphere Corporation(http://dietrich.ganx4.com/nusoap/ )開發。NuSOAP的一個優勢是不需要擴展庫的支持,這種特性使得NuSoap可以用於所有的PHP環境,不受服務器安全設置的影響。
方法一:直接調用
復制代碼 代碼如下:
<?
include(‘NuSoap.php');
// 創建一個soapclient對象,參數是server的WSDL
$client = new soapclient(‘http://localhost/Webservices/Service.asmx?WSDL', ‘wsdl');
// 參數轉為數組形式傳遞
$aryPara = array(‘strUsername'=>'username', ‘strPassword'=>MD5(‘password'));
// 調用遠程函數
$aryResult = $client->call(‘login',$aryPara);
//echo $client->debug_str;
$document=$client->document;
echo <<<SoapDocument
<?xml version=”1.0″ encoding=”GB2312″?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/” xmlns:SOAP-ENV=”http://schemas.xmlsoap.org/soap/envelope/” 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:si=”http://soapinterop.org/xsd“>
<SOAP-ENV:Body>
$document
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
SoapDocument;
?>
方法二:代理方式調用
復制代碼 代碼如下:
<?
require(‘NuSoap.php');
//創建一個soapclient對象,參數是server的WSDL
$client=new soapclient(‘http://localhost/Webservices/Service.asmx?WSDL', ‘wsdl');
//生成proxy類
$proxy=$client->getProxy();
//調用遠程函數
$aryResult=$proxy->login(‘username',MD5(‘password'));
//echo $client->debug_str;
$document=$proxy->document;
echo <<<SoapDocument
<?xml version=”1.0″ encoding=”GB2312″?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/” xmlns:SOAP-ENV=”http://schemas.xmlsoap.org/soap/envelope/” 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:si=”http://soapinterop.org/xsd“>
<SOAP-ENV:Body>
$document
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
SoapDocument;
?>
許多使用NuSoap 調用.NET WebService或J2EE WebService的朋友可能都遇到過中文亂碼問題,下面介紹這一問題的出現的原因和相應的解決方法。
NuSoap調用WebService出現亂碼的原因:
通常我們進行WebService開發時都是用的UTF-8編碼,這時我們需要設置:
$client->soap_defencoding = ‘utf-8′;
同時,需要讓xml以同樣的編碼方式傳遞:
$client->xml_encoding = ‘utf-8′;
至此應該是一切正常了才對,但是我們在輸出結果的時候,卻發現返回的是亂碼。
NuSoap調用WebService出現亂碼的解決方法:
實際上,開啟了調試功能的朋友,相信會發現$client->response返回的是正確的結果,為什麼$result = $client->call($action, array(‘parameters' => $param)); 卻是亂碼呢?
研究過NuSoap代碼後我們會發現,當xml_encoding設置為UTF-8時,NuSoap會檢測decode_utf8的設置,如果為true,會執行 PHP 裡面的utf8_decode函數,而NuSoap默認為true,因此,我們需要設置:
$client->soap_defencoding = ‘utf-8′;
$client->decode_utf8 = false;
$client->xml_encoding = ‘utf-8′;
補充介紹
NuSOAP 是 PHP 環境下的 WEB 服務編程工具,用於創建或調用 WEB 服務。它是一個開源軟件,當前版本是 0.7.2 ,支持 SOAP1.1 、 WSDL1.1 ,可以與其他支持 SOAP1.1 和 WSDL1.1 的系統互操作。 NuSOAP 完全由PHP語言編寫,由一系列 PHP 類組成,不需要擴展庫的支持,這種特性使得 NuSOAP 可以用於所有的 PHP 環境,不受服務器安全設置的影響。
1. NuSOAP 的獲取和安裝
NuSOAP 項目建立在 SourceForge 上,網絡地址是: http://sourceforge.net/projects/nusoap/ ,這裡,可以下載到 NuSOAP 的最新的版本。
NuSOAP 的安裝比較簡單,把下載的 NuSOAP 的文件拷貝到服務器上,可以放在獨立的目錄裡,也可以與程序代碼放在相同的目錄裡,只要你的 PHP 代碼能夠訪問到這些文件就可以了。
本文的測試環境基於 PHP4.3.2 和 NuSOAP 0.7.2 版本, NuSOAP 安裝在 WEB 目錄“ /nusoap ”裡,有兩個子目錄, lib 和 samples 。其中, lib 目錄下存放 NuSOAP 的所有源代碼文件, samples 目錄下是NuSOAP開發小組提供一些的例子。測試文件存放在 WEB 目錄“ /nusoap ”裡。
2. NuSOAP 的使用
NuSOAP 由一 PHP 的類組成,其中最常用到的是類soap_server和類soalclient。類soap_server 用於創建 WEB 服務,類soapclient在訪問WEB服務時會用到。
2.1 一個簡單的例子: Hello World
這個例子將利用 NuSOAP 創建一個簡單的 WEB 服務,並利用 NuSOAP 創建一個客戶端程序,調用這個服務。這個服務唯一的功能就是向客戶端返回一個字符串“ Hello World ”。首先,創建 WEB 服務程序代碼文件“ /nusoap/nusoap_server1.php ”:
//把 NuSOAP 的源文件包含到當前的代碼文件裡
復制代碼 代碼如下:
<?php
require_once(“lib/nusoap.php”);
//定義服務程序
function hello() {
return ‘Hello World!';
}
//初始化服務對象 , 這個對象是類 soap_server 的一個實例
$soap = new soap_server; //調用服務對象的 register 方法注冊需要被客戶端訪問的程序。
//只有注冊過的程序,才能被遠程客戶端訪問到。
$soap->register(‘hello'); //最後一步,把客戶端通過 post 方式提交的數據,傳遞給服務對象的 service 方法。
//service 方法處理輸入的數據,調用相應的函數或方法,並且生成正確的反饋,傳回給客戶端。
$soap->service($HTTP_RAW_POST_DATA);
?>
至此, WEB 服務程序代碼文件已經建好,接下來,創建一個客戶端程序代碼文件“ /nusoap/nusoap_client1.php ”,調用 WEB 服務:
復制代碼 代碼如下:
//把 NuSOAP 的源文件包含到當前的代碼文件裡
<?php
require_once(“lib/nusoap.php”);
//初始化客戶端對象,這個對象是類 soapclient 的一個實例,
//把服務程序的 URL 地址傳遞給soapclient類的構造函數。
$client = new soapclient(‘http://127.0.0.1/nusoap/nusoap_server1.php'); //利用客戶端對象的 call 方法調用 WEB 服務的程序
$str=$client->call(‘hello'); //客戶端對象的 getError() 方法可以用來檢查調用過程是否出現錯誤。
//如果沒有錯誤, getError() 方法返回 false ;如果有錯誤, getError()方法返回錯誤信息。
if (!$err=$client->getError()) {
echo ” 程序返回 :”,htmlentities($str,ENT_QUOTES);
} else {
echo ” 錯誤 :”,htmlentities($err,ENT_QUOTES);
}
?>
至此,客戶端程序也建立好了,打開浏覽器,訪問客戶端程序,看一下結果。這個例子,浏覽器會顯示字符串:“程序返回 :Hello World! ”
2.2 傳遞參數和返回錯誤信息的方法
再通過例子說明傳遞參數和返回錯誤信息的方法。這個例子實現兩個字符串的連接,參數是兩個字符串,返回值是由兩個參數連接而成的字符串。首先,創建服務程序代碼文件“ /nusoap/nusoap_server2.php ”,完整的代碼如下:
復制代碼 代碼如下:
<?php
require_once(“lib/nusoap.php”);
function concatenate($str1,$str2) {
if (is_string($str1) && is_string($str2))
return $str1 . $str2;
else
return new soap_fault(‘ 客戶端 ‘,”,'concatenate 函數的參數應該是兩個字符串 ‘);
}
$soap = new soap_server;
$soap->register(‘concatenate');
$soap->service($HTTP_RAW_POST_DATA);
?>
與 2.1 節 WEB 服務程序的代碼比較,這裡的代碼結構大體是相同的。注意以下兩點:
服務程序的定義不同,帶有兩個參數。 NuSOAP 注冊服務程序的過程還是一樣的,都是調用服務對象的 register 方法。
這裡使用了 NuSOAP 的一個新類 soap_fault 。當傳入的兩個參數有一個不是字符串時,程序通過這個類把錯誤信息返回給客戶端。這個類的構造函數有 4 個參數:
fault
code
必填參數 , 建議值為“ Client ”或“ Server ”,指明錯誤是客戶端的錯誤還是服務端的錯誤。
faultactor
預留項,現在還沒有使用
faultstring
錯誤的描述信息
faultdetail
可選項, XML 格式的數據 , 說明詳細的錯誤信息
客戶端程序代碼文件“ /nusoap/nusoap_client2.php ”的完整內容如下 :
復制代碼 代碼如下:
<?php
require_once(“lib/nusoap.php”);
$client = new soapclient(‘http://127.0.0.1/nusoap/nusoap_server2.php');
$parameters=array(‘ 字符串 1′,' 字符串 2′);
$str=$client->call(‘concatenate',$parameters);
if (!$err=$client->getError()) {
echo ” 程序返回 :”,$str;
} else {
echo ” 錯誤 :”,$err;
}
?>
NuSOAP 的客戶端調用帶參數的 WEB 服務時,使用數組傳遞參數。 $parameters 是一個數組,其中依次是每個參數的值。客戶端在調用遠程的服務程序時,使用帶有兩個參數的 call 方法,第一個參數是服務程序的名稱,第二個參數是服務程序的參數數組,這裡是 $parameters 。通過浏覽器訪問上面的客戶端程序,浏覽器上會顯示字符串:“ 程序返回 : 字符串 1 字符串 2 ”
接下來,試著給 WEB 服務程序傳入錯誤參數,修改上面的客戶端程序,把生成參數數組的語句改成: $parameters=array(“ 字符串 ”,12) ,再通過浏覽器訪問客戶端程序,浏覽器上會顯示字符串:“錯誤 : 客戶端 : concatenate 函數的參數應該是兩個字符串”。 WEB 服務程序判斷傳入的參數有一個不是字符串,通過 soap_fault 給客戶端返回錯誤信息。
2.3 調試的方法
NuSOAP中常用的調試方法有三種:
2.3.1 soapclient 類的 request 和 response 成員變量
最直接的調試方法就是檢查訪問 WEB 服務的過程中,客戶端發出的 request 信息和服務端返回的 response 信息。 soapclient 類的 request 和 response 成員變量包含這些信息,在程序中顯示出這兩個變量的內容,可以幫助分析程序運行的情況。看下面的代碼:
復制代碼 代碼如下:
<?php
require_once(“lib/nusoap.php”);
$client = new soapclient(‘http://127.0.0.1/nusoap/nusoap_server2.php');
$parameters=array(‘ 字符串 1′,' 字符串 2′);
$str=$client->call(‘concatenate',$parameters);
if (!$err=$client->getError()) {
echo ” 程序返回 :”,$str;
} else {
echo ” 錯誤 :”,$err;
}
//下面顯示request和response 變量的內容
echo ‘<p/>';
echo ‘Request:';
echo ‘<pre>',htmlspecialchars($client->request,ENT_QUOTES),'</pre>';
echo ‘Response:';
echo ‘<pre>',htmlspecialchars($client->response,ENT_QUOTES ),'</pre>';
?>
2.3.2 soapclient 類的 debug_str 成員變量
soapclient 類的 debug_str 成員變量提供了更為詳細的調試信息,查看這個變量的內容,可以更好地幫助程序調試。
2.3.3 WEB 服務程序提供的調試方法
WEB 服務程序代碼中,在創建 soap_server 類的實例前,定義變量 $debug=1 。調試信息作為備注,放在 SOAP 消息的尾部返回客戶端,客戶端通過查看 WEB 服務的 response 信息來查看調試信息。
復制代碼 代碼如下:
<?php
require_once(“lib/nusoap.php”);
function concatenate($str1,$str2) {
if (is_string($str1) && is_string($str2))
return $str1 . $str2;
else
return new soap_fault(‘ 客戶端 ‘,”,'concatenate 函數的參數應該是兩個字符串 ‘);
}
$debug=1; //定義調試
$soap = new soap_server;
$soap->register(‘concatenate');
$soap->service($HTTP_RAW_POST_DATA);
?>
2.4 對 WSDL 的支持
NuSOAP 內部通過類 “WSDL” 實現對 WSDL 的支持。對於 NuSOAP 的用戶來說,不需要關心內部的WSDL類是如何工作的,正確地使用 soap_server 類和 soapclient 類就可以實現對 WSDL 的支持。
2.4.1 創建支持 WSDL 的 WEB 服務
為了實現 WEB 服務程序對 WSDL 的支持,需要使用 soap_server 的 configureWSDL 方法,並且在調用 soap_server 的 register 方法注冊 WEB 服務程序時,需要提供更詳細的參數。看下面的代碼,代碼的文件名是 “/nusoap/nusoap_server3.php”。
復制代碼 代碼如下:
<?php
require_once(“lib/nusoap.php”);
function concatenate($str1,$str2) {
if (is_string($str1) && is_string($str2))
return $str1 . $str2;
else
return new soap_fault(‘ 客戶端 ‘,”,'concatenate 函數的參數應該是兩個字符串 ‘);
}
$soap = new soap_server;
$soap->configureWSDL(‘concatenate'); // 初始化對 WSDL 的支持
// 注冊服務
$soap->register(‘concatenate',
array(“str1″=>”xsd:string”,”str2″=>”xsd:string”), // 輸入參數的定義
array(“return”=>”xsd:string”) // 返回參數的定義
);
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : ”;
$soap->service($HTTP_RAW_POST_DATA);
?>
現在打開浏覽器,訪問剛才建立的文件,http://127.0.0.1/nusoap/nusoap_server3.php,結果如下:
concatenate
View the WSDL for the service. Click on an operation name to view it's details.
concatenate
點擊函數名稱concatenate,可以看到對函數的描述。點擊”WSDL”,或者訪問WEB服務文件,並在後面加上查詢字符串”?wsdl”(http://127.0.0.1/nusoap/nusoap_server3.php?wsdl),可以得到WEB服務的WSDL內容。
2.4.2 通過 WSDL 調用 WEB 服務
通過 WSDL 調用 WEB 服務,與不通過 WSDL 調用 WEB 服務,程序的結構大體相同。區別在於,通過 WSDL 調用 WEB 服務,初始化 soapclient 類時,傳入兩個參數到 soapclient 的構造函數,第一個參數是 WSDL 文件的地址,第二個參數指定是否使用 WSDL ,指定為 true 即可。看下面的代碼,代碼的文件名是 “ /nusoap/nusoap_client3.php ”
復制代碼 代碼如下:
<?php
require_once(“lib/nusoap.php”);
$client = new soapclient(‘http://127.0.0.1/nusoap/nusoap_server3.php?wsdl',true);
$parameters=array(‘ 字符串 1′,' 字符串 2′);
$str=$client->call(‘concatenate',$parameters);
if (!$err=$client->getError()) {
echo ” 程序返回 :”,$str;
} else {
echo ” 錯誤 :”,$err;
}
?>
2.4.3 代理的使用
NuSOAP 提供代理的方法調用遠程 WEB 服務。這種方法,在客戶端程序裡面創建一個遠程服務的代理對象,通過代理直接調用遠程的 WEB 服務,而不需要通過 soalclient 類的 call 方法。看下面的代碼。
復制代碼 代碼如下:
<?php
require_once(“lib/nusoap.php”);
$client = new soapclient(‘http://127.0.0.1/nusoap/nusoap_server3.php?wsdl',true);
$proxy=$client -> getProxy(); // 創建代理對象 (soap_proxy 類 )
$str=$proxy->concatenate(” 參數 1″,” 參數 2″); // 直接調用 WEB 服務
if (!$err=$proxy->getError()) {
echo ” 程序返回 :”,$str;
} else {
echo ” 錯誤 :”,$err;
}
?>