简介 PHP 的 SOAP 扩展可以用来提供和使用 Web Services。换句话说,PHP 开发者可以利用这个 PHP 扩展来写他们自己的 Web Services,也可以写一些客户端来使用给定的 Web Services。
PHP5 中的这个 SOAP 扩展目的是为了实现 PHP 对 Web Services 的支持。与其它实现 PHP 对 Web Services 的支持的方法不同,SOAP 扩展是用 C 写的,因此它比其它方法具有速度优势。
扩展中的类 SoapClient 类 这个类用来使用 Web Services。SoapClient 类可以作为给定 Web Services 的客户端。 它有两种操作形式:
在 WSDL 模式中,构造器可以使用 WSDL 文件名作为参数,并自动从 WSDL 中提取使用服务时所需要的信息。
Non-WSDL 模式中使用参数来设置使用服务时所需要的信息。
这个类有许多可以用来使用服务的有用的方法。其中__soapCall() 是最重要的。这个方法可以用来调用服务中的某个操作。
SoapServer 类 这个类可以用来提供 Web Services。与 SoapClient 类似,SoapServer 也有两种操作模式:WSDL 模式和 non-WSDL模式。这两种模式的意义跟 SoapClient 的两种模式一样。在 WSDL 模式中,服务实现了 WSDL 提供的接口;在 non-WSDL 模式中,参数被用来管理服务的行为。
在 SoapServer 类的众多方法中,有三个方法比较重要。它们是 SoapServer::setClass()、SoapServer::addFunction() 和 SoapServer::handle()。
SoapServer::setClass()方法设定用来实现 Web Services 的类。SoapServer::setClass 所设定的类中的所有公共方法将成为 Web Services 的操作(operation)。
SoapServer::addFunction() 方法用来添加一个或多个作为 Web Services 操作(operation)的函数。
SoapServer:: handle() 方法指示 Web Services 脚本开始处理进入的请求。Web Services 脚本是用 PHP 脚本写的一个或多个 SoapServer 对象的实例。尽管你可以有不止一个的 SoapServer 对象,但通常的习惯是一个脚本只拥有一个 SoapServer 实例。在调用 SoapServer::handle() 方法之前,Web Services 脚本会使用设置在 SoapServer 对象实例上的任何信息来处理进入的请求和输出相应的内容。
SoapFault 类 这个类从 Exception 类继承而来,可以用来处理错误。SoapFault 实例可以抛出或获取 Soap 错误的相关信息并按程序员的要求处理。
这个类可以用来描述 SOAP headers。它只是一个只包含构造器方法的数据容器。
SoapParam 类 SoapParam 也是一个只包含构造器方法的数据容器。这个方法可以用来描述传递给 Web Services 操作的参数。在 non-WSDL 模式中这是一个很有用的类,可以用来传递所期望格式的参数信息。
SoapVar 类 SoapVar 也是一个只包含构造器的低级类,与 SoapHeader 和 SoapParam 类相似。这个类可以用来给一个Web Services 操作传递编码参数。这个类对 non-WSDL 中传递类型信息是非常有用的。
注:SoapParam 和 SoapVar 主要用来封装用于放入 SOAP 请求中的数据,他们主要在 non-WSDL 模式下使用。事实上,在 WSDL 模式下,SOAP 请求的参数可以通过数组方式包装,SOAP 扩展会根据 WSDL 文件将这个数组转化成为 SOAP 请求中的数据部分,所以并不需要这两个类。而在 non-WSDL 模式下,由于没有提供 WSDL 文件,所以必须 通过这两个类进行包装。
SoapHeader 类用来构造 SOAP 头,SOAP 头可以对 SOAP 的能力进行必要的扩展。SOAP 头的一个主要作用就是用于简单的身份认证。
扩展安装 php.ini配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 extension=soap [soap] ; Enables or disables WSDL caching feature. ; http://php.net/soap.wsdl-cache-enabled soap.wsdl_cache_enabled=1 ; Sets the directory name where SOAP extension will put cache files. ; http://php.net/soap.wsdl-cache-dir soap.wsdl_cache_dir="G:/xampp/tmp" ; (time to live) Sets the number of second while cached file will be used ; instead of original one. ; http://php.net/soap.wsdl-cache-ttl soap.wsdl_cache_ttl=86400 ; Sets the size of the cache limit . (Max. number of WSDL files to cache) soap.wsdl_cache_limit=5
这些配置项主要是用来指定 PHP 处理 WSDL 文件时使用缓存的行为。这几个配置项分别说明:是否开启 WSDL 文件缓存、文件缓存位置、缓存时间、以及最大缓存文件数量。启用缓存会加快 PHP 处理 WSDL 文件的速度,但最好在调试代码时关闭缓存,以避免一些因缓存行为而出现的问题。
WSDL 模式测试 hello.wsdl文件 在这个 Hello World 例子的服务中有一个被命名为 greet 的操作。这个操作有一个字符串形式的名字参数并返回一个字符串形式的 Hello + 名字。
所用到的 WSDL 如下:
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 <wsdl:definitions xmlns:impl='http://localhost/test/php-soap/wsdl/helloService' xmlns:intf='http://localhost/test/php-soap/wsdl/helloService' xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/' xmlns:wsdlsoap='http://schemas.xmlsoap.org/wsdl/soap/' xmlns:xsd='http://www.w3.org/2001/XMLSchema' targetNamespace='http://localhost/test/php-soap/wsdl/helloService' > <wsdl:types> <schema elementFormDefault='qualified' xmlns:impl='http://localhost/test/php-soap/wsdl/helloService' xmlns:intf='http://localhost/test/php-soap/wsdl/helloService' xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/' xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace='http://localhost/test/php-soap/wsdl/helloService' > <element name='greet' > <complexType> <sequence> <element name='name' type ='xsd:string' /> </sequence> </complexType> </element> <element name='greetResponse' > <complexType> <sequence> <element name='greetReturn' type ='xsd:string' /> </sequence> </complexType> </element> </schema> </wsdl:types> <wsdl:message name='greetRequest' > <wsdl:part name='parameters' element='impl:greet' /> </wsdl:message> <wsdl:message name='greetResponse' > <wsdl:part name='parameters' element='impl:greetResponse' /> </wsdl:message> <wsdl:portType name='helloService' > <wsdl:operation name='greet' > <wsdl:input name='greetRequest' message='impl:greetRequest' /> <wsdl:output name='greetResponse' message='impl:greetResponse' /> </wsdl:operation> </wsdl:portType> <wsdl:binding name='helloServiceSoapBinding' type ='impl:helloService' > <wsdlsoap:binding transport='http://schemas.xmlsoap.org/soap/http' style='document' /> <wsdl:operation name='greet' > <wsdlsoap:operation soapAction='helloService#greet' /> <wsdl:input name='greetRequest' > <wsdlsoap:body use='literal' /> </wsdl:input> <wsdl:output name='greetResponse' > <wsdlsoap:body use='literal' /> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name='helloService' > <wsdl:port binding='impl:helloServiceSoapBinding' name='helloService' > <wsdlsoap:address location='http://localhost/test/php-soap/wsdl/hello_service_wsdl.php' /> </wsdl:port> </wsdl:service> </wsdl:definitions>
WSDL 服务端 下面是 WSDL 模式的服务使用 SOAP 扩展来实现提供服务的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 <?php function greet($param ){ $value = 'Hello ' . $param ->name; $result = [ 'greetReturn' => $value ]; return $result ; } $server = new SoapServer('hello.wsdl' );$server ->addFunction('greet' );$server ->handle();
WSDL 客户端 1 2 3 4 5 6 7 8 9 10 <?php try { $client = new SoapClient('hello.wsdl' ); $result = $client ->__soapCall('greet' , [ ['name' => 'xpmozong' ] ]); printf ("Result = %s" , $result ->greetReturn); } catch (Exception $e ) { printf ("Message = %s" ,$e ->__toString()); }
运行客户端
1 2 $ php test.php Result = Hello xpmozong
non-WSDL 模式 non-WSDL 模式服务端 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?php function greet($param ){ $value = 'Hello ' .$param ; return new SoapParam($value , 'greetReturn' ); } $server = new SoapServer(null, [ 'uri' => 'http://localhost/test/php-soap/non-wsdl/helloService' ]); $server ->addFunction('greet' );$server ->handle();
non-WSDL 模式客户端 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php try { $client = new SoapClient(null, [ 'location' => 'http://localhost/test/php-soap/non-wsdl/hello_service_non_wsdl.php' , 'uri' => 'http://localhost/test/php-soap/non-wsdl/helloService' ]); $result = $client ->__soapCall('greet' , [ new SoapParam('xpmozong' , 'name' ) ]); printf ("Result = %s" , $result ); } catch (Exception $e ) { printf ("Message = %s" ,$e ->__toString()); }
运行客户端
1 2 $ php test.php Result = Hello xpmozong
在 non-WSDL 模式中,因为没有使用 WSDL,传递了一个包含服务所在位置(location)和服务 URI 的参数数组作为参数。然后像 WSDL 模式中一样调用__soapCall() 方法,但是使用了 SoapParam 类用指定格式打包参数。返回的结果将获取 greet 方法的响应。
注:客户端实例化时所传入的服务 URI,实际上,我们可以把它看作该服务的一个命名空间(namespace)。客户端所传入的 URI 必与服务端所命名的 URI 一样。