大多数的Web Service是使用Java语言的,因此在PHP中很少用到Web Service,用PHP写Web Service程序也就成为了比较冷门的知识点,其实仔细研究一下,似乎没有想象中复杂

下面我们就来用PHP写Web Service程序:

1、Server端

首先,定义一个类,在其中实现方法,然后用SoapServer将此类发布出去。

data_service.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。

function add($x, $y){

return $x + $y;

$server = new SoapServer(null, ["uri" => "php.test"]);

$server->addFunction("add");

$server->handle();

2、Client端

client.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

100800

响应包:

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

900

我们需要注意,如果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:Server

WSDL generation is not supported yet

看完了本文。我们可能觉得用PHP写Web Service程序似乎很简单,但实际操作起来并没有我们看起来那么轻松,会遇到许多的现实问题,需要我们花大量时间和精力去考证和解决。或许,这也是我们学习的乐趣之所在吧!