• 如何使用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
    <?php
    define('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
    $client = new SoapClient("http://127.0.0.1/createsoap/hello.wsdl");
      
    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的开发人员来说很简单的。

  • 相关阅读:
    【Java】这个案例帮你搞懂Date类型
    MySQL学习笔记十一:触发器
    MySQL学习笔记十:游标/动态SQL/临时表/事务
    MySQL学习笔记九:索引
    MySQL学习笔记八:存储过程与自定义函数
    MySQL学习笔记七:常用函数
    MySQL学习笔记六:表的创建及管理
    MySQL学习笔记五:数据类型
    MySQL学习笔记四:数据库创建与常见操作
    MySQL学习笔记三:MySQL5.7安装后期设置
  • 原文地址:https://www.cnblogs.com/sandea/p/3705709.html
Copyright © 2020-2023  润新知