Home  >  Article  >  php教程  >  如何使用PHP实现一个WebService

如何使用PHP实现一个WebService

WBOY
WBOYOriginal
2016-06-13 09:39:04804browse

WSDL

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

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

<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):

<?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:

<?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,那么,你修改一下这个方法,我是这么做的:

//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。很简单。

<?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文件里面查找

,这里的url(具体url是根据你的目录确定的)就是你要提供给.NET开发人员使用的。不过别高兴太早,后面要加:“?wsdl”,http://xxxxxxxxxxxxxxxxxxxx/server.php?wsdl这样才是对的,不信你可以将url拷贝到浏览器的地址栏里看下就知道了。

.NET开发人员获得你给他的url之后,就可以在自己的项目里面添加一个服务引用或者web引用了,然后就可以根据提示完成相关操作,对于使用.NET的开发人员来说很简单的。

Statement:
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