越來越多的架構偏向於面向接口和面向服務的設計了,當我們把抽象的落地變為實際的時候,我們感覺到了代碼的厚度。而當我們把具體的業務再進一步抽象,我們就能發現藏在細節深處的回饋。
php可以提供service,利用一些契約(或者說協議)來進行通信和交換數據。常用的有soap,rpc,restful api(json傳輸為主流)等方式。我在jm的時候,曾經用過thrift寫的接口,給java組的童鞋提供數據接口。thirift讓不同編程語言的項目可以很好協調在一起,形成的文檔也較為清晰,但是畢竟又借用了三方的東西,增加維護成本和學習成本。
關於restful api,我是非常喜歡的。基於資源的設計,清晰無比的請求方式(get,put,post,del),加上json友好的格式化數據傳遞,有點大道至簡的禪味。我手里正在做的一個私人項目,就是基於這種方式寫的。restful api要聊的太多了,不過不是我今天要談的,還是聊聊 soap吧。
簡單說,soap是基於XML的交換數據的協議。因為是xml映射數據關系,所以不在乎是什么編程語言或者平台(其實我更喜歡json方式,更純粹)。
php在實現soap的方式有兩種,一種是wsdl方式,一種是無wsdl方式。今天我只談wsdl方式。
實現原理如我整理之圖所示:

soap分為server端和client端,server端運行起來之后一直handle,然后client端利用生成好的wsdl文件規則,去注冊使用server端的接口,獲取返回數據(xml之類的).
類比java中的socket編程,也是client去監聽server,server一直阻塞等待調用。
代碼如下。
server parts:
<?php /** * Created by PhpStorm. * User: Administrator * Date: 2015/12/3 * Time: 16:44 */ class Server { /** * 獲取用戶列表 * * @return mixed * @author freephp at 2015-12-3 */ function userList() { $data = $this->user_model->find(); return $data; } /** * 獲取派對列表 * * @return array * @author freephp at 2015-12-3 */ function partyList() { // some codes to do return array( 'party_name' => 'cn', 'history' => 1995 ); } } try { $soap = new SoapServer("server.wsdl"); // new一個SoapServer對象出來,此為php標准庫里對象 } catch (Exception $e) { echo $e->getMessage();die(); } //This uri is your SERVER ip. $soap->setClass("Server"); $soap->handle(); // handle it
client端代碼如下:
<?php /**
* client調用.加了很多調試try,catch.
**/ try { $client = new SoapClient(null, array( 'location' => self::$serverUrl, 'uri' => self::$uri, ) ); } catch (Exception $e) { // print the error info echo $e->getMessage(); die(); } try { $data = $client->useList(self::$verifyID, $xml); } catch (SoapFault $ex) { // 調試打印出錯誤堆棧和最后一次請求信息 print $ex->getMessage(); print $ex->getTraceAsString(); echo $client->__getLastResponse(); echo $client->__getLastResponseHeaders(); die(); }
在編寫過程中,我遇到許多不同報錯,比如 VersionMismatch,not xml等。
出現VersionMismatch的時候要先檢查一下你client端傳的xml的version是和server端的一致。soap有兩個版本,1.1和1.2。必須設置成同一種。這就像和歪果仁聊天一樣,大家溝通的語言要一致,不然沒轍。然而我遇到這個報錯的原因卻因為我在server端打了調試信息,讓server返回的不是xml數據,自然就報錯了。所以請調試的時候一定要在 client這邊調用完成后打印。
