如何使用PHP实现一个WebService
WSDL
WSDL(网络服务描述语言,Web Services Description Language)是一门基于 XML 的语言,用于描述 Web Services 以及如何对它们进行访问。这种文档可描述某个 Web service。它可规定服务的位置,以及此服务提供的操作(或方法)。
一个 WSDL 文档的主要结构是类似这样的:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<definitions> <types> definition of types........ </types> <message> definition of a message.... </message> <portType> definition of a port....... </portType> <binding> definition of a binding.... </binding></definitions> |
WSDL 文档可包含其它的元素,比如 extension 元素,以及一个 service 元素,此元素可把若干个 web services 的定义组合在一个单一的 WSDL 文档中。
PHP生成WSDL
类代码(SoapDiscovery.class.php):

<?php
class SoapDiscovery {
private $class_name = '';
private $service_name = ''; /**
* SoapDiscovery::__construct() SoapDiscovery class Constructor.
*
* @param string $class_name
* @param string $service_name
**/
public function __construct($class_name = '', $service_name = '') {
$this->class_name = $class_name;
$this->service_name = $service_name;
} /**
* SoapDiscovery::getWSDL() Returns the WSDL of a class if the class is instantiable.
*
* @return string
**/
public function getWSDL() {
if (empty($this->service_name)) {
throw new Exception('No service name.');
}
$headerWSDL = "<?xml version="1.0" ?>n";
$headerWSDL.= "<definitions name="$this->service_name" targetNamespace="urn:$this->service_name" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="urn:$this->service_name" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns="http://schemas.xmlsoap.org/wsdl/">n";
$headerWSDL.= "<types xmlns="http://schemas.xmlsoap.org/wsdl/" />n"; if (empty($this->class_name)) {
throw new Exception('No class name.');
} $class = new ReflectionClass($this->class_name); if (!$class->isInstantiable()) {
throw new Exception('Class is not instantiable.');
} $methods = $class->getMethods(); $portTypeWSDL = '<portType name="'.$this->service_name.'Port">';
$bindingWSDL = '<binding name="'.$this->service_name.'Binding" type="tns:'.$this->service_name."Port">n<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />n";
$serviceWSDL = '<service name="'.$this->service_name."">n<documentation />n<port name="".$this->service_name.'Port" binding="tns:'.$this->service_name."Binding"><soap:address location="http://".$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].$_SERVER['PHP_SELF']."" />n</port>n</service>n";
$messageWSDL = '';
foreach ($methods as $method) {
if ($method->isPublic() && !$method->isConstructor()) {
$portTypeWSDL.= '<operation name="'.$method->getName()."">n".'<input message="tns:'.$method->getName()."Request" />n<output message="tns:".$method->getName()."Response" />n</operation>n";
$bindingWSDL.= '<operation name="'.$method->getName()."">n".'<soap:operation soapAction="urn:'.$this->service_name.'#'.$this->class_name.'#'.$method->getName()."" />n<input><soap:body use="encoded" namespace="urn:$this->service_name" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />n</input>n<output>n<soap:body use="encoded" namespace="urn:$this->service_name" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />n</output>n</operation>n";
$messageWSDL.= '<message name="'.$method->getName()."Request">n";
$parameters = $method->getParameters();
foreach ($parameters as $parameter) {
$messageWSDL.= '<part name="'.$parameter->getName()."" type="xsd:string" />n";
}
$messageWSDL.= "</message>n";
$messageWSDL.= '<message name="'.$method->getName()."Response">n";
$messageWSDL.= '<part name="'.$method->getName()."" type="xsd:string" />n";
$messageWSDL.= "</message>n";
}
}
$portTypeWSDL.= "</portType>n";
$bindingWSDL.= "</binding>n";
return sprintf('%s%s%s%s%s%s', $headerWSDL, $portTypeWSDL, $bindingWSDL, $serviceWSDL, $messageWSDL, '</definitions>');
} /**
* SoapDiscovery::getDiscovery() Returns discovery of WSDL.
*
* @return string
**/
public function getDiscovery() {
return "<?xml version="1.0" ?>n<disco:discovery xmlns:disco="http://schemas.xmlsoap.org/disco/" xmlns:scl="http://schemas.xmlsoap.org/disco/scl/">n<scl:contractRef ref="http://".$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].$_SERVER['PHP_SELF']."?wsdl" />n</disco:discovery>";
}
} ?>

使用方法(服务端server.php):
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<?phpdefine('WSDL_URL','hello.wsdl'); //定义WSDL文件路径ini_set('soap.wsdl_cache_enabled','0'); //关闭WSDL缓存 //WSDL文件不存在时自动创建if(!file_exists(WSDL_URL)){ require_once 'SoapDiscovery.class.php'; $disco = new SoapDiscovery('HelloWorld','IELIWB_HelloWorld'); $str = $disco->getWSDL(); file_put_contents(WSDL_URL,$str);} //SOAP开启并接收Client传入的参数响应 $server = new SoapServer(WSDL_URL);$server->setClass('HelloWorld');$server->handle(); //测试定义公开的类class HelloWorld { private $nombre = ''; public function __construct($name = 'World') {$this->name = $name;} public function greet($name = '') {$name = $name?$name:$this->name;return 'Hello '.$name.'.';} public function serverTimestamp() {return time();} }?> |
客户端client.php:
|
1
2
3
4
5
6
7
8
9
10
11
12
|
<?php try { $result = $client->greet('ieliwb'); var_dump($result); echo "The answer isresult";}catch (SoapFault $f){ echo "Error Message: {$f->getMessage()}";}?> |
创建 Webservice
1. 创建wsdl
- 非标准的webservice,可能只能PHP才能访问
- 标准的webservice,就必须要使用wsdl(webservice description language,就是用XML语法标准来描述你的服务内容,我是这么理解的)
在这里我只介绍标准的webservice。那么如何创建wsdl呢?对于PHP来说这确实是件很不容易的事情,有人说用zend studio创建很方便,这是一种方法。但对于那些不喜欢用zend studio的人来说,会觉得创建一个webservice还要安装zend studio,太强人所难了,我就是,嘿嘿。
在这里我介绍一个简单的方法,到网上下载SoapDiscovery.class.php类,里面有个公用方法:getWSDL,这个方法末尾是用的return,那么,你修改一下这个方法,我是这么做的:
|
1
2
3
4
|
//return sprintf('%s%s%s%s%s%s', $headerWSDL, $portTypeWSDL, $bindingWSDL, $serviceWSDL, $messageWSDL, '</definitions>');//生成wsdl文件,将上面的return注释$fso = fopen($this->class_name . ".wsdl" , "w");fwrite($fso, sprintf('%s%s%s%s%s%s', $headerWSDL, $portTypeWSDL, $bindingWSDL, $serviceWSDL, $messageWSDL, '</definitions>')); |
现在生成wsdl的类有了,SoapDiscovery.class.php。
我只要再准备一个提供服务的类或者函数就可以创建wsdl了。比如我有个类:person,文件名为:person.class.php★,里面有两个方法,一个是say,一个是run。很简单。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<?php class person { public function say() { return("i'm speaking."); } public function run() { return("i'm running,don't disturb me please."); } }?> |
到这里有两个类了:SoapDiscovery.class.php和person.class.php。
开始正式生成wsdl:创建文件server.php。将以下内容拷贝进去,运行即可生成一个person.wsdl文件

<?php
include("person.class.php");
include("SoapDiscovery.class.php"); //第一个参数是类名(生成的wsdl文件就是以它来命名的),即person类,第二个参数是服务的名字(这个可以随便写)。
$disco = new SoapDiscovery('person','Person');
$disco->getWSDL();
?>

2. 创建webservice服务端程序
将server.php文件的内容清空,复制以下代码进去:

<?php
include("person.class.php");
$objSoapServer = new SoapServer("person.wsdl");//person.wsdl是刚创建的wsdl文件
//$objSoapServer = new SoapServer("server.php?wsdl");//这样也行
$objSoapServer->setClass("person");//注册person类的所有方法
$objSoapServer->handle();//处理请求
?>

3. 创建webservice客户端程序,测试webservice是否有效,文件名是:client.php

<?php
$client = new SoapClient("person.wsdl");
//$client = new SoapClient("server.php?wsdl");//这样也行
echo($client->say());
echo "<br />";
echo($client->run());
echo "<br />";
?>

OK,结束。.NET如果要使用的话,你只要提供一个url给他就行了。
获得url的方法:你可以先到person.wsdl文件里面查找<soap:address location="http://xxxxxxxxxxxxxxxxxxxx/server.php" />,这里的url(具体url是根据你的目录确定的)就是你要提供给.NET开发人员使用的。不过别高兴太早,后面要加:“?wsdl”,http://xxxxxxxxxxxxxxxxxxxx/server.php?wsdl这样才是对的,不信你可以将url拷贝到浏览器的地址栏里看下就知道了。
.NET开发人员获得你给他的url之后,就可以在自己的项目里面添加一个服务引用或者web引用了,然后就可以根据提示完成相关操作,对于使用.NET的开发人员来说很简单的。
如何使用PHP实现一个WebService的更多相关文章
- 【Web学习日记】——在IIS上发布一个WebService
没有开发过程,只是发布过程 一.前提 开发使用的是VS2013 从来没有做过Web的发布,在网上找例子,看到的总是与自己的情况不相符,而且也有人提出了VS2013发布网站的问题,但解决方案却很少,好不 ...
- 在IIS上发布一个WebService,再发布一个网站调用这个WebService(实例)
首先描述一下先决条件:IIS可用,VS2005可用. 好,现在开始: 首先写一个WebService并把它发布到IIS上: 在IIS上的默认网站下新建一个“虚拟目录”,取名为“webservice1” ...
- WebService-01-使用jdk发布第一个WebService服务并调用
Webservice是SOAP+XML,SOAP是基于Http的,Http底层是Socket,先回顾一下Socket: Server: public class Server { public sta ...
- 自定义及发布一个webservice服务
自定义及发布一个webservice服务 - 声明 某个业务服务为webservice服务 通过@webservice 注解来声明 - 发布webservice服务 ...
- (二)发布第一个WebService服务与DSWL文档解析
1. 编写接口 package service; import javax.jws.WebService; /** * 第一个webservice服务, * @WebService注解表示这是一个we ...
- 一个WebService Demo
1.建立一个Asp.net Web网站,添加新项Web服务MyMath.asmx.编写如下代码: using System; using System.Collections.Generic; usi ...
- 如何从40亿整数中找到不存在的一个 webservice Asp.Net Core 轻松学-10分钟使用EFCore连接MSSQL数据库 WPF实战案例-打印 RabbitMQ与.net core(五) topic类型 与 headers类型 的Exchange
如何从40亿整数中找到不存在的一个 前言 给定一个最多包含40亿个随机排列的32位的顺序整数的顺序文件,找出一个不在文件中的32位整数.(在文件中至少确实一个这样的数-为什么?).在具有足够内存的情况 ...
- 利用MyEclipse开发一个webservice接口
一直以来对于接口这个东西都很好奇,各种客户也一直在说那个什么什么数据我们提供给你们一个接口就好了,结果还是不是很明白.于是乎就有了下面的小故事,接下来我们就进入正文吧 ---大概可以分为这样的步骤 1 ...
- 基于 jdk1.7 发布一个 WebService 服务
1 服务端的发布 第一步: 创建一个 Java 项目第二步: 创建一个类, 加入 Webservice 注解第三步: 提供一个方法 sayHello第四步: 在 main 方法中调用 jdk 提供的发 ...
随机推荐
- java开发:分享一下MemCached的使用
在项目开发中,有些不经常修改的数据,我们通常都会选择使用缓存.其中一种方式,就是memcached. windows系统中,我们需要下载并安装memcached. 地址如:D:\memcached\m ...
- 转 Android 4.0后,自定义Title报错 You cannot combine custom titles with other title feature
自定义Titlebar时为了避免冲突 需要修改:AndroidManifest.xml android:theme="@style/mystyle" styles.xml文件中 ...
- Android Studio ndk-Jni开发详细
http://www.open-open.com/lib/view/open1451917048573.html Java Native Interface (JNI)标准是java平台的一部分,它允 ...
- html5 canvas 圆形抽奖的实例
年底没啥,抽空学习了canvas,写了个html5抽奖的代码,造了个轮子,有用的童鞋可以拿走. 其中,canvas.onclick触发抽奖行为,概率可以在core.lottery()函数上添加,美化也 ...
- poi-3.11-beta2-20140822.jar操作excel方法
poi-3.11-beta2-20140822.jar操作excel方法 根据不同类型读取值的方法: // 获取单元格内不同类型的值 public String getValueByType(HSSF ...
- 博客迁到CSDN
之前一直是博客园和CSDN博客同步更新 现在不在博客园继续写博客,十一国庆节假后只用CSDN博客了.祝各位访客国庆节快乐! CSDN博客地址: http://blog.csdn.net/it_liuc ...
- Xcode 真机无法调试
关于只能在模拟器上测试不能在真机测试的问题 2. 在 buildSetting 里面搜索bitcode,更改为 No 即可.
- Objective-C 【动态类型检测&响应方法】
------------------------------------------- 动态类型检测 代码: #import <Foundation/Foundation.h> @inte ...
- OC6_目录及文件的创建
// // main.m // OC6_目录及文件的创建 // // Created by zhangxueming on 15/6/19. // Copyright (c) 2015年 zhangx ...
- FileZilla ftp服务器安装
在官网下载server版本的FileZilla,我下载的是(The latest stable version of FileZilla Server is 0.9.41) 然后直接安装就可了,我由于 ...