PHP and Web Services [转]

WBOY
Release: 2016-06-23 14:35:21
Original
754 people have browsed it

 

学习材料是: [Wrox]Professional Open Source Web Services
Chapter 8 PHP and Web Services
英文版电子书下载[pdf]

全文分为三个部分: 概述。PHP进行Web Services开发的优点,在Unix系统上安装配置PHP 在PHP中使用SOAP。NuSOAP工具包,NuSOAP的高级Web Service功能,如HTTP代理,SOAP over HTTPS,document style messaging。还将讨论如何解决一些PHP Web Services编程将会遇到的问题,如安全问题,语言到数据类型的映射 PHP中的XML-RPC。XML-RPC的特性,XML-RPC与SOAP的对比,然后使用Useful, Inc.实现来创建XML-RPC的客户端和服务器程序 下面是第一部分。


Section 1. 概述 PHP中已经通过绑定了Expat parser内置了XML支持,额外的还可以使用一些扩展程序(extension),如domxml(通过使用libxml库提供DOM, Xpath, Xlink支持),xslt(为复杂的第三方XSLT库如Sablotron和libxslt提供的外包程序)。

另一个对Web Service 开发有用的PHP扩展程序是CURL(Client URL Library)。CURL允许你通过不同的协议,如HTTP, HTTPS, FTP, telnet, LDAP来通讯,其中的HTTPS对Web Services与服务器进行安全连接尤其有用。

SOAP vs XML-RPC 优缺点: 强大的类型扩展 (SOAP) 用户自定义字符集,如US-ASCII, UTF-8, UTF-16 (SOAP) Specifies recipient [指定容器?] (SOAP) 容器遇到无法理解的报文则失败 (SOAP) 易于使用 (XML-RPC) 设计简单 (XML-RPC) 配置PHP: Apache: 为了让PHP作为Apache的模块方式运行,使用 --with-apxs选项编译,如 --with-apxs=/www/bin/apxs。[我现在使用的Apache2, 我编译的PHP使用的选项是--with-apxs2=/usr/sbin/apxs] DOMXML: 可选功能,对解析XML文档十分有帮助。需要预先安装好libxml库(版本>=2.4.2),编译时使用 --with-dom=DIR 选项(缺省DIR为/usr)
http://www.xmlsoft.org/downloads.html
libxml 2.6.4 - sources - 2.52 MB
XSLT: 可选功能,对转换XML资料为其他类型的文档有帮助。编译时使用 --enable-xslt --with-xslt-sablot 选项。必须预先安装Sablotron XSLT库(http://www.gingerall.com/),(缺省DIR为/usr/lib或者/usr/local/lib)。
Sablotron 1.0.1 - sources - 470 kB
CURL: 如前所述,若提供SSL支持则是必须安装的。编译时使用 --with-curl=DIR 选项。也同样需要预先安装CURL库(版本>=7.0.2-beta)。 [我的PHP已经安装了。CURL Information: libcurl/7.10.7 OpenSSL/0.9.7c zlib/1.1.4]

继续昨天的学习。今天主要是关于NuSOAP




Section 2. SOAP NuSOAP介绍: NuSOAP是一组开源的,用来通过HTTP收发SOAP消息的PHP类,由NuSphere Corporation ( http://www.nusphere.com/
) 开发。NuSOAP的一个优势是他不是一个扩展程序,而是纯粹用PHP代码写的,所以适用范围比较广。

结构:
安装配置: 从 http://dietrich.ganx4.com/nusoap/ 下载,从zip文件中解出nusoap.php文件放到include目录,在你的脚本前面加上
include('nusoap.php');
就搞定了。

范例: 下面是一个简单的SOAP client程序: soap_client.php 执行

//simple client
require('nusoap.php');

//要发送的变量
$myString="world";

//parameters must be passed as an array
//变量必须要转换成数组的形式
$parameters=array($myString);

//创建一个soapclient对象,参数是server的URL
$s=new soapclient('http://www.douzi.org/me/php_ws/soap_server.php');

//调用远程方法,返回值存放在$result
//返回值为PHP的变量类型,如string, integer, array
$result=$s->call('echoString', $parameters);

//错误检测
if (!$err=$s->getError()) {
echo 'Result: '.$result; //success
} else {
echo 'Error: '.$err;
}

//调试,以下是SOAP请求(request)和回应(response)的报文,包括HTTP头
echo "<xmp>".$s->request."</xmp>";
echo "<xmp>".$s->response."</xmp>";

?>


相应的server端程序: soap_server.php

//simple server
require('nusoap.php');

//创建一个新的soap_server对象,并注册允许远程调用的方法
$s=new soap_server;
$s->register('echoString');
$s->register('echoArray');

/*
[文章中说: 缺少了注册这一步,任何PHP函数都将可以进行远程调用,这将是一个极大的安全隐患。但是我尝试过注册是必须的。而且只有将结果return的函数才能直接声明为远程方法,比如echo()就不行,而strtolower()就可以。]
*/

function echoString($inputString) {
//类性检查
if(is_string($inputString)) {
return "Hello, ".$inputString;
} else {
//soap_fault类用于产生错误信息
return new soap_fault('client', '', 'The parameter to this service must be a string.');
//soap_fault(faultcode, faultactor, faultstring, faultdetail);
//上面是错误处理类的构造函数的格式
//faultcode 必须值。可以设置为client或server,来表明错误发生在哪一端。
//faultactor 在NuSOAP中尚未实现。
//faultstring 错误信息。
//faultdetail 详细错误信息。你可以使用XML标记。

//除了构造函数外,soap_fault类还有一个serialize()方法
//它将错误信息序列化,然后返回一个完整的SOAP报文,范例:
/*
$fault = new soap_fault('client', '', 'The inputString parameter must not be empty');
echo $fault->serialize();
*/
}
}

//演示数组类型的使用
function echoArray($inputString) {
return $inputString[0]."+".$inputString[1];

}

//最后一步是把所有的收到的post数据都传递给SOAP server的service方法。它将处理请求,并调用相应的函数。
$s->service($HTTP_RAW_POST_DATA);
?>



复杂数据类型的使用: 数组。以下是生成的SOAP的Body部分代码:




string1
string2





生成复合数据类型(compound types samples),使用soapval。以下是生成的SOAP的Body部分代码:


123 Freezing Lane
Nome
Alaska
12345

1234567890
0987654321




程序范例: soapval.php 执行

//soapval: general compound types samples
include('nusoap.php');

$address=array(
'street'=>'123 Freezing Lane',
'city'=>'Nome',
'state'=>'Alaska',
'zip'=>12345,
'phonenumbers'=>array('home'=>'1234567890', 'mobile'=>'0987654321')
);

$s=new soapval('myAddress', 'address', $address, '', 'http://myNamespace.com');

print "<xmp>".$s->serialize()."</xmp>";

?>



WSDL WSDL是一种用于描述Web Service的XML语言。它是一种机读格式,把所有的访问服务所必须的信息提供给Web Service客户端。NuSOAP专门提供一个类进行WDSL文件的解析,并且从中提取信息。soapclient对象使用wsdl类来减轻开发者调用服务的难度。通过WSDL信息的帮助来创建报文,程序员仅仅需要知道操作的名字和参数就能调用它。

通过NuSOAP使用WSDL提供以下几点优点: 所有的服务元文件,如命名空间(namespaces),endpoint URLs,参数名(parameter names)等等都可以直接从WSDL文件获得,这样就允许客户端动态的适应服务器端的变化。因为从服务器随时可以获得,所以这些数据不再需要在用户脚本中使用硬性编码。 它允许我们使用soap_proxy类。这个类派生自soapclient类,增加了WDSL文件中详细列出的操作所对应的方法。现在用户通过它可以直接调用这些方法。 soapclient类包含一个getProxy()方法,它返回一个soap_proxy类的一个对象。soap_proxy类派生自soapclient类,增加了对应于WSDL文档中定义的操作的方法,并且允许用户调用一个endpoint的远程方法。这仅仅适用于soapclient对象用WDSL文件初始化的情况。优点是易于用户使用,缺点是性能--PHP中创建对象是耗时的--且不为功利目的服务(and this functionality serves no utilitarian purpose)。
范例: wsdl.php 执行

//wsdl的一个简单演示文件
include('nusoap.php');

//SOAP源为一个提供明星生卒年月的service
//首先我们创建一个soapclient对象,把WSDL文件的URL传递给构造函数,
//之后还要使用第二个参数以便使client知道我们传递过来的是WSDL,而不是SOAP endpoint。
$s=new soapclient('http://www.abundanttech.com/webservices/deadoralive/deadoralive.wsdl', 'wsdl');

//生成proxy类
$p=$s->getProxy();

//调用远程函数
$sq=$p->getTodaysBirthdays();

if (!$err=$p->getError()) {
print_r($sq);
} else {
print "ERROR: $err";
}

print 'REQUEST:<xmp>'.$p->request.'</xmp>';
print 'RESPONSE:<xmp>'.str_replace('>\nresponse).'</xmp>';

?>


附:一个有用的Web Services的演示站点: http://www.mindreef.net/soapscope/wsdldemo

 

 这是最后一节,感觉PHP还是很适合做client的。这节主要是关于XML-RPC的。
我原来曾经有一篇XML-RPC学习笔记,内容和这个很类似。




Section 3. XML-RPC XML-RPC的数据类型

XML-RPC仅支持有限的几种数据类型。下面是和PHP数据类型的的对应关系:

Useful Inc. XML-RPC实现 -- phpxmlrpc

我们使用的XML-RPC工具包是Useful, Inc.的Edd Dumbill制作的,下载网址 http://phpxmlrpc.sourceforge.net/ ,其中完整包括client和server的XML-RPC实现。

客户端和服务器端分别由 xmlrpc_client 类和 xmlrpc_server 类实现,主要用于接收和发送XML-RPC报文。xmlrpcval 类用于将PHP变量编码为XML-RPC等价数据类型和向远程方法传递参数。相反的过程使用 xmlrpc_decode() 函数。XML-RPC报文使用 xmlrpcmsg 类通过传递给它一个参数表来创建。

xmlrpc_client 类发送使用 xmlrpcmsg 类创建的XML-RPC报文,在服务器端, xmlrpc_server 类解析这些收到的报文为 xmlrpcmsg 对象。然后这个对象被作为一个单独参数传递给用户函数。该函数必须返回一个 xmlrpcresp 对象, xmlrpc_server 类将其用于序列化并返回给客户端。这个基本的体系结构如下图所示。

安装和配置

在 http://phpxmlrpc.sourceforge.net/ 下载,解包,然后将 xmlrpc.inc 和 xmlrpcs.inc 放置到你的包含路径即可。

客户端程序首部只要加入下面的包含语句:
include('xmlrpc.inc');

服务器端程序首部要加入下面的包含语句:
include('xmlrpc.inc');
include('xmlrpcs.inc'); //服务器端代码

范例

XML-RPC client: xmlrpc_client.php 执行


//xmlrpc_client.php
//XML-RPC客户端演示程序
require('xmlrpc.inc');

//创建client对象, 三个参数依次为 path, hostname, port
$s=new xmlrpc_client('/xmlrpc/xmlrpc_server.php', 'www.windix.local', 80);

//create xmlrpcval object, which allows the encoding of our variable
//创建xmlrpcval对象,将我们的PHP变量编码为XML-RPC需要的XML形式
$inputString=new xmlrpcval('world', 'string');

//create an array of parameters
//尽管我们只有一个参数,但仍然要转换成数组的形式,因为xmlrpcmsg的第二个参数是一个参数表
$parameters=array($inputString);

//create the message object
//创建XML-RPC报文,参数分别为 远程方法名 和 参数表
$msg=new xmlrpcmsg('echoString', $parameters);

//send the message, get the response
//发送报文,返回值$rsp为一个xmlrpcresp对象,它包含以下三个方法:
//faultCode() 出错代码,如果成功将返回0
//faultString() 出错信息
//value() 返回值,以xmlrpcval对象形式存在,PHP使用前需要进行解码
$rsp=$s->send($msg);

//check for errors
if($rsp->faultcode()==0) {
//decode the response to a PHP type
//xmlrpc_decode()函数用于将xmlrpcval对象解码
$response=xmlrpc_decode($rsp->value());

//print results
print '

'
Copy after login
';
var_dump($response);
print ';
} else {
//print errors
print 'Error: '.$rsp->faultcode().', '.$rsp->faultstring().'
';
}

//show messages
//然后我们来查看一下报文内容
$msg->createpayload();
print 'REQUEST:<xmp>'.$msg->payload.'</xmp>';
print 'RESPONSE:<xmp>'.$rsp->serialize().'</xmp>';

?>


XML-RPC server: xmlrpc_server.php

//xmlrpc_server.php
//XML-RPC服务器端演示程序
require('xmlrpc.inc');
require('xmlrpcs.inc');

//service that echoes a string
//我们用于处理远程调用的自定义函数
//注意,该函数必须且只能有一个类型为xmlrpcmsg对象的参数
function echoString($msg) {

//decode parameters into navtive types
//首先使用xmlrpc_decode函数进行解码
$inputString=xmlrpc_decode(array_shift($msg->params));

//check for input parameter validity
//检查数据类型是否正确
if(is_string($inputString)) {
return new xmlrpcresp( new xmlrpcval('Hello, '.$inputString, 'string') );

} else { //or return a fault
return new xmlrpcresp(0, $xmlrpcerruser+1, "Parameter type ".gettype($inputString)." mismatched expected type.");
}

}

//instantiate the server object and register our functions
//初始化server对象,并注册我们的函数
//下面这个数组称为"dispatch map",其中以输出函数名为主键的项又是一个数组
//包含以下三个成员:
// function 实际调用的函数名,在这里我们的函数名也是echoString,同服务名一样
// signature 可选。输入和输出参数的类型,最后一个是输出参数,前面的都是输入参数
// docstring 可选。包含你的服务的文档,甚至可以有HTML内容。

//xmlrpc_server还包含第二个可选初始化参数,如果设置为0,则服务不会立刻处理请求
//需要使用server的service()方法进程才能被执行

$s=new xmlrpc_server(array(
'echoString' => array(
'function' => 'echoString',
'signature' => array( array('string','string') ),
'docstring' => 'This service echoes Hello+input stirng.'
)
));
?>

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!