PHP中很少用到WebService,最近才研究了一下,似乎沒有想象中復雜。
1、Server端
定義一個類,在其中實現方法,然后用SoapServer將此類發布出去。
data_service.php:
- <?php
- class DataAction{
- public function add($x, $y){
- return $x + $y;
- }
- }
- //定義SoapServer,不指定wsdl,必須指定uri,相當於asmx中的namespace
- $server = new SoapServer(null, ["uri" => "php.test"]);
- //指定此SoapServer發布DataAction類中的所有方法
- $server->setClass("DataAction");
- $server->handle>
- ?>
也可以不用class,直接發布function。
- <?php
- function add($x, $y){
- return $x + $y;
- }
- $server = new SoapServer(null, ["uri" => "php.test"]);
- $server->addFunction("add");
- $server->handle();
- ?>
2、Client端
client.php:
- <?php
- //SoapClient即WebService客戶端,其uri與Server端保持一致,location是WebService服務地址
- $client = new SoapClient(null, ["uri" => "php.test", "location" => "http://192.168.90.81/test/data_service.php"]);
- //調用add方法,傳入參數
- echo $client->add(100, 200);
- unset($client);
- ?>
抓包看看:
- 請求包:
- POST /test/data_service.php HTTP/1.1
- Host: 192.168.90.81
- Connection: Keep-Alive
- User-Agent: PHP-SOAP/5.4.3
- Content-Type: text/xml; charset=utf-8
- SOAPAction: "php.test#add"
- Content-Length: 512
- <?xml version="1.0" encoding="UTF-8"?>
- <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="php.test" 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/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:add><param0 xsi:type="xsd:int">100</param0><param1 xsi:type="xsd:int">800</param1></ns1:add></SOAP-ENV:Body></SOAP-ENV:Envelope>
- --------------------------------
- 響應包:
- HTTP/1.1 200 OK
- Server: nginx/1.2.0
- Date: Thu, 07 Jun 2012 06:51:33 GMT
- Content-Type: text/xml; charset=utf-8
- Content-Length: 488
- Connection: keep-alive
- X-Powered-By: PHP/5.4.3
- <?xml version="1.0" encoding="UTF-8"?>
- <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="php.net" 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/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:addResponse><return xsi:type="xsd:int">900</return></ns1:addResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
需要注意,如果PHP是以FastCGI方式運行,且只啟動了一個進程 ,由於php-cgi.exe的單線程模型,訪問client.php時其又會向data_service.php發送請求,但當前請求未處理完畢,data_service.php無法響應,會造成卡死得不到結果。
比如nginx如果沒有使用負載均衡,所有php請求都轉發到同一個php-cgi進程,就肯定會卡死。請負載均衡到不同進程上,或者換用isapi模式。
使用這種方式沒有定義wsdl,沒想明白雙方是如何約定通訊的。另外顯然,用這種方式肯定無法跨語言訪問服務,因為我們訪問data_service.php?wsdl拿不到wsdl,返回如下:
- <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
- <SOAP-ENV:Body>
- <SOAP-ENV:Fault>
- <faultcode>SOAP-ENV:Server</faultcode>
- <faultstring>WSDL generation is not supported yet</faultstring>
- </SOAP-ENV:Fault>
- </SOAP-ENV:Body>
- </SOAP-ENV:Envelope>