php 中,在 php.ini 檔案中開啟了 php_soap.dll 擴充後,就可以支援 soap 了。
在soap擴充庫中,主要包括三種對象。
1、soapserver
用于建立php伺服器端頁面時定義可被調用的函數及傳回響應資料。建立一個soapserver對象的文法格式如下:
$soap = new soapserver($wsdl, $array);
其中,$wsdl為shoap使用得wsdl檔案,wsdl 是描述 web service的一種标準格式,若将$wsdl設定為null,則表示不使用wsdl模式。$array是soapserver的屬性資訊,是一個數組。
soapserver對象的addfunction方法是用來聲明哪個函數可以被用戶端調用,文法格式如下:
$soap->addfunction($function_name);
其中,$soap是一個soapserver對象,$function_name是需要被調用的函數名。
soapserver對象的handle方法用來處理使用者輸入并調用相應的函數,最後傳回給用戶端處理的結果。文法格式如下:
$soap->handle([$soap_request]);
其中,$soap是一個soapserver對象,$soap_request是一個可選參數,用來表示使用者的請求資訊。如果不指定$soap_request,則表示伺服器将接收使用者的全部請求。
2、soapcliet
用于調用遠端伺服器上的soapserver頁面,并實作了對相應函數的調用。建立一個soapclient對象的文法格式如下:
$soap = new soapclient($wsdl,$array);
其中,參數$wsdl和$array與soapserver相同。
建立soapclient對象後,調用服務端頁面中的函數相當于調用了soapclient的方法,建立文法如下:
$soap->user_function($params);
其中,$soap是一個soapclient對象,user_function是伺服器端要調用的函數,$params 是要傳入函數的參數。
3、soapfault
soapfault用于生成soap通路過程中可能出現的錯誤。建立一個soapfault對象的文法格式如下:
$fault = new soapfault($faultcode,$faultstring);
其中,$faultcode是使用者定義的錯誤代碼,$faultstring是使用者自定義的錯誤資訊。soapfault 對象會在伺服器端頁面出現錯誤時自動生成,或者通過使用者自行建立soapfault對象時生成。對于 soap通路時出現的錯誤,用戶端可通過捕捉soapfalut對象來獲得相應的錯誤資訊。
在用戶端捕獲soapfault對象後,可以通過下面的代碼獲得錯誤代碼和錯誤資訊:
$fault->faultcode;//錯誤代碼
$fault->faultstring;//錯誤資訊
其中,$fault是在前面建立的soapfault對象。
不論是soapserver還是soapclient,都接收兩個參數,其中第二個參數是option,它支援若幹選項,這裡我們用到的有:
uri:命名空間,用戶端和服務端需要使用相同的命名空間
location:用戶端用,用來指定服務端程式的通路位址,也就是本例第二段代碼的程式位址。
trace:用戶端用,為true時可以擷取服務端和用戶端通信的内容,以供調試。
soapserver.php

<?php
//先建立一個soapserver對象執行個體,然後将我們要暴露的函數注冊,
//最後的handle()用來處理接受的soap請求
error_reporting(7); //正式釋出時,設為 0
date_default_timezone_set('prc'); //設定時區
/* 幾個供client端調用的函數 */
function reverse($str)
{
$retval = '';
if (strlen($str) < 1) {
return new soapfault ('client', '', 'invalid string');
}
for ($i = 1; $i <= strlen($str); $i++) {
$retval .= $str [(strlen($str) - $i)];
return $retval;
}
function add2numbers($num1, $num2)
if (trim($num1) != intval($num1)) {
return new soapfault ('client', '', 'the first number is invalid');
if (trim($num2) != intval($num2)) {
return new soapfault ('client', '', 'the second number is invalid');
return ($num1 + $num2);
function gettime()
$time = date('y-m-d h:i:s', time());
return $time;
$soap = new soapserver (null, array('uri' => "httr://test-rui"));
$soap->addfunction('reverse');
$soap->addfunction('add2numbers');
$soap->addfunction('gettime');
$soap->addfunction(soap_functions_all);
$soap->handle();
?>
soapclient.php

error_reporting(7);
try {
$client = new soapclient (null, array('location' => "http://www.yiigo.com/soapserver.php", 'uri' => "http://test-uri"));
$str = "this string will be reversed";
$reversed = $client->reverse($str);
echo "if you reverse '$str', you will get '$reversed'";
$n1 = 20;
$n2 = 33;
$sum = $client->add2numbers($n1, $n2);
echo "<br>";
echo "if you try $n1 + $n2, you will get $sum";
echo "the remoye system time is: " . $client->gettime();
} catch (soapfault $fault) {
echo "fault! code:" . $fault->faultcode . " string:" . $fault->faultstring;
if you reverse 'this string will be reversed', you will get 'desrever eb lliw gnirts siht'
if you try 20 + 33, you will get 53
the remoye system time is: 2012-05-28 16:14:29
通過soapheader實作身份認證

class server
public function auth($a)
{
if ($a != '123456789') {
throw new soapfault('server', '使用者身份認證資訊錯誤');
}
public function say()
return 'hi';
$srv = new soapserver(null, array('uri' => 'http://localhost/namespace'));
$srv->setclass('server');
$srv->handle();
用戶端

$cli = new soapclient(null,
array('uri' => 'http://localhost/namespace/',
'location' => 'http://localhost/server.php',
'trace' => true));
//auth為服務端要處理的函數 12345689為參數
$h = new soapheader('http://localhost/namespace/',
'auth', '123456789', false, soap_actor_next);
$cli->__setsoapheaders(array($h));
echo $cli->say();
} catch (exception $e) {
echo $e->getmessage();
}
注意觀察server.php中的server類有一個方法“auth”,剛好與header的名稱對應,方法auth的參數$u,就是soapheader的data,soapserver接收到這個請求會,先調用auth方法,并把“123456789”作為參數傳遞給該方法。mustunderstand參數為false時,即便沒有auth這個方法,say方法也會被調用,但是如果它為true的話,如果auth方法不存在,就會傳回一個soapfault告知該header沒有被處理。actor參數指名那些role必須處理該header,這兒我了解得不是太透徹,不好說。

$file = $this->getsoapwsdl();
$client = new soapclient($file);//url可以通過浏覽器通路,不能直接調用解決
$param = array('userid' => 'test', 'merchantid' => 'test');
$returnst = $client->checkuser($param);
print_r($returnst->checkuserresult);
public function getsoapwsdl()
{ //定期将url的檔案儲存到本地
$file = mage::getbasedir() . ds . 'data' . ds . 'shengda' . ds . 'export.wsdl';
if (time() > filemtime($file) + 7 * 86400) {
$url = "http://jf.sdo.com/exchangescore/exchangeservice.asmx?wsdl";
include_once(bp . ds . "lib/snoopy.class.php");
$snoopy = new snoopy;
$snoopy->fetch($url); //擷取所有内容
$snoopy->read_timeout = 4;
$wsdl = $snoopy->results;
if ($snoopy->status == '200' && !$snoopy->timed_out) {
if (!is_dir(dirname($file))) {
mkdir(dirname($file));
}
file_put_contents($file, $wsdl);
return $file;