php实现webservice

本文详细介绍如何使用PHP实现WebService,包括创建WSDL文件、搭建服务端及客户端程序的具体步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

php有两个扩展可以实现web service,一个是NuSoap,一个是php 官方的soap扩展,由于soap是官方的,所以我们这里以soap来实现web service.由于默认是没有打开soap扩展的,所以自己先看一下soap扩展有没有打开。

 在soap编写web service的过程中主要用到了SoapClient,SoapServer,SoapFault三个类。

SoapClient类

这个类用来使用Web services。SoapClient类可以作为给定Web services的客户端。
它有两种操作形式:

* WSDL 模式

* Non-WSDL 模式

在WSDL模式中,构造器可以使用WSDL文件名作为参数,并从WSDL中提取服务所使用的信息。

non-WSDL模式中使用参数来传递要使用的信息。

SoapServer类

这个类可以用来提供Web services。与SoapClient类似,SoapServer也有两种操作模式:WSDL模式和non-WSDL模式。这两种模式的意义跟 SoapClient的两种模式一样。在WSDL模式中,服务实现了WSDL提供的接口;在non-WSDL模式中,参数被用来管理服务的行为。

在SoapServer类的众多方法中,有三个方法比较重要。它们是SoapServer::setClass(),SoapServer::addFunction()和SoapServer::handle()。

下面给出实例:
定义一个提供服务的php类,这个类所提供的函数就是web service对外提供的服务

复制代码
 1  <? php
 2  Class  PersonInfo
 3  {
 4       /* *
 5       *    返回姓名
 6       *    @return string 
 7       *
 8        */
 9       public   function  getName(){
10           return   " My Name is Chance " ;
11      }
12  }

13 ?>

复制代码
下面给出服务器端的代码:

 1 <?php
 2 //包含提供服务的类进来
 3 require_once('PersonInfo.php');
 4 
 5 //wsdl方式提供web service,如果生成了wsdl文件则可直接传递到//SoapServer的构造函数中
 6 //$s = new SoapServer('PersonInfo.wsdl');
 7 
 8 //doesn't work 只有location不能提供web service
 9 //output:looks like we got no XML document
10 //$s = new SoapServer(null,array("location"=>"http://localhost/Test/MyService/Server.php"));
11 
12 //下面两种方式均可以工作,只要指定了相应的uri
13 //$s = new SoapServer(null,array("uri"=>"Server.php"));
14 $s = new SoapServer(null,array("location"=>"http://localhost/Test/MyService/Server.php","uri"=>"Server.php"));
15 
16 $s -> setClass("PersonInfo");
17 
18 $s -> handle();
19 ?>

下面是客户端代码:


 1 <?php
 2 try{
 3     //wsdl方式调用web service
 4     //wsdl方式中由于wsdl文件写定了,如果发生添加删除函数等操作改动,不会反应到wsdl,相对non-wsdl方式
 5     //来说不够灵活
 6     //$soap = new SoapClient("http://localhost/Test/MyService/PersonInfo.wsdl");
 7     
 8     //non-wsdl方式调用web service    
 9     //在non-wsdl方式中option location系必须提供的,而服务端的location是选择性的,可以不提供
10     $soap = new SoapClient(null,array('location'=>"http://localhost/Test/MyService/Server.php",'uri'=>'Server.php'));
11     
12     //两种调用方式,直接调用方法,和用__soapCall简接调用
13     $result1 = $soap->getName();
14     $result2 = $soap->__soapCall("getName",array());
15     echo $result1."<br/>";
16     echo $result2;
17     
18 }catch(SoapFault $e){
19     echo $e->getMessage();
20 }catch(Exception $e){
21     echo $e->getMessage();
22 }
23 
24 ?>







WSDL

WSDL(网络服务描述语言,Web Services Description Language)是一门基于 XML 的语言,用于描述 Web Services 以及如何对它们进行访问。这种文档可描述某个 Web service。它可规定服务的位置,以及此服务提供的操作(或方法)。

一个 WSDL 文档的主要结构是类似这样的:

01<definitions>
02    <types>
03       definition of types........
04    </types>
05    <message>
06       definition of a message....
07    </message>
08    <portType>
09       definition of a port.......
10    </portType>
11    <binding>
12       definition of a binding....
13    </binding>
14</definitions>

WSDL 文档可包含其它的元素,比如 extension 元素,以及一个 service 元素,此元素可把若干个 web services 的定义组合在一个单一的 WSDL 文档中。

PHP生成WSDL

类代码(SoapDiscovery.class.php):

01<?php
02class SoapDiscovery {
03    private $class_name = '';
04    private $service_name = '';
05     
06    /**
07     * SoapDiscovery::__construct() SoapDiscovery class Constructor.
08     *
09     * @param string $class_name
10     * @param string $service_name
11     **/
12    public function __construct($class_name = '', $service_name = '') {
13        $this->class_name = $class_name;
14        $this->service_name = $service_name;
15    }
16     
17    /**
18     * SoapDiscovery::getWSDL() Returns the WSDL of a class if the class is instantiable.
19     *
20     * @return string
21     **/
22    public function getWSDL() {
23        if (empty($this->service_name)) {
24            throw new Exception('No service name.');
25        }
26        $headerWSDL = "<?xml version="1.0" ?>n";
27        $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";
28        $headerWSDL.= "<types xmlns="http://schemas.xmlsoap.org/wsdl/" />n";
29  
30        if (empty($this->class_name)) {
31            throw new Exception('No class name.');
32        }
33         
34        $class = new ReflectionClass($this->class_name);
35         
36        if (!$class->isInstantiable()) {
37            throw new Exception('Class is not instantiable.');
38        }
39         
40        $methods = $class->getMethods();
41         
42        $portTypeWSDL = '<portType name="'.$this->service_name.'Port">';
43        $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";
44        $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";
45        $messageWSDL = '';
46        foreach ($methods as $method) {
47            if ($method->isPublic() && !$method->isConstructor()) {
48                $portTypeWSDL.= '<operation name="'.$method->getName()."">n".'<input message="tns:'.$method->getName()."Request" />n<output message="tns:".$method->getName()."Response" />n</operation>n";
49                $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";
50                $messageWSDL.= '<message name="'.$method->getName()."Request">n";
51                $parameters = $method->getParameters();
52                foreach ($parameters as $parameter) {
53                    $messageWSDL.= '<part name="'.$parameter->getName()."" type="xsd:string" />n";
54                }
55                $messageWSDL.= "</message>n";
56                $messageWSDL.= '<message name="'.$method->getName()."Response">n";
57                $messageWSDL.= '<part name="'.$method->getName()."" type="xsd:string" />n";
58                $messageWSDL.= "</message>n";
59            }
60        }
61        $portTypeWSDL.= "</portType>n";
62        $bindingWSDL.= "</binding>n";
63        return sprintf('%s%s%s%s%s%s', $headerWSDL, $portTypeWSDL, $bindingWSDL, $serviceWSDL, $messageWSDL, '</definitions>');
64    }
65     
66    /**
67     * SoapDiscovery::getDiscovery() Returns discovery of WSDL.
68     *
69     * @return string
70     **/
71    public function getDiscovery() {
72        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>";
73    }
74}
75  
76?>

使用方法(服务端server.php):

01<?php
02define('WSDL_URL','hello.wsdl');        //定义WSDL文件路径
03ini_set('soap.wsdl_cache_enabled','0');    //关闭WSDL缓存
04  
05//WSDL文件不存在时自动创建
06if(!file_exists(WSDL_URL))
07{
08    require_once 'SoapDiscovery.class.php';
09    $disco = new SoapDiscovery('HelloWorld','IELIWB_HelloWorld');
10    $str = $disco->getWSDL();
11    file_put_contents(WSDL_URL,$str);
12}
13  
14//SOAP开启并接收Client传入的参数响应
15$server = new SoapServer(WSDL_URL);
16$server->setClass('HelloWorld');
17$server->handle();
18  
19  
20//测试定义公开的类
21class HelloWorld {
22    private $nombre = '';
23    public function __construct($name = 'World') {$this->name = $name;}
24    public function greet($name = '') {$name = $name?$name:$this->name;return 'Hello '.$name.'.';}
25    public function serverTimestamp() {return time();}
26}
27?>

客户端client.php:

01<?php
02$client = new SoapClient("http://127.0.0.1/createsoap/hello.wsdl");
03  
04try {
05        $result = $client->greet('ieliwb');
06        var_dump($result);
07        echo "The answer isresult";
08}
09catch (SoapFault $f){
10        echo "Error Message: {$f->getMessage()}";
11}
12?>
创建 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//return sprintf('%s%s%s%s%s%s', $headerWSDL, $portTypeWSDL, $bindingWSDL, $serviceWSDL, $messageWSDL, '</definitions>');
2//生成wsdl文件,将上面的return注释
3$fso = fopen($this->class_name . ".wsdl" , "w");
4fwrite($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。很简单。

01<?php
02    class person
03    {
04        public function say()
05        {
06            return("i'm speaking.");
07        }
08        public function run()
09        {
10            return("i'm running,don't disturb me please.");
11        }
12    }
13?>

到这里有两个类了:SoapDiscovery.class.php和person.class.php。

开始正式生成wsdl:创建文件server.php。将以下内容拷贝进去,运行即可生成一个person.wsdl文件

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

2. 创建webservice服务端程序

将server.php文件的内容清空,复制以下代码进去:

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

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

1<?php
2    $client = new SoapClient("person.wsdl");
3    //$client = new SoapClient("server.php?wsdl");//这样也行
4    echo($client->say());
5    echo "<br />";
6    echo($client->run());
7    echo "<br />";
8?>

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的开发人员来说很简单的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值