它是一個開源軟體,是完全採用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;
}
?>