返回首页

{A}{A2的}
这是一个关于如何用PHP编写的SOAP的WebServices的增强的教程。介绍
PHP与SOAP连接是相当不错的,希望共享一个中央位置上的业务逻辑。本文介绍如何WebServices的可以用PHP编写的轻松,至少他们可以用C#访问。代码保持简单,甚至中间的初学者也可以了解如何编写Web服务,但足够灵活,以先进的开发使用。
因为默认SoapServer类缺少一些功能,我已经写了一个小的框架,以支持功能,如自动WSDL生成或传输大的数据,我会一步一步解释。
对于那些只希望看到的代码,一个文件的例子可以发现,在下载一节。定义服务
服务是不是比quot; thingquot大家谁被授权可以要求做了一些预定义的任务,并返回结果。
服务可以实现对象 - 但一定要牢记,服务程序,而不是面向对象的。所以提到quot; thingquot;是一个对象,任务,相当于方法和参数,其结果是该方法的返回值。
重要的是,Web服务以及定义,使客户知道如何使用这些服务和方法。对于此Web服务的描述,anbsp;已建立基于XML的语言:WSDL的。WSDL代
撰写一个WSDL文件是额外的工作,那么为什么不让它PHP​​本身产生?在PHP中的类型问题
WSDL需要描述所有类型的参数和结果,在XSD(XML架构)。但在PHP中,变量的类型没有指定,默认情况下,有没有办法来确定使用方法,如果程序员不知道他们的类型。所以,当你不想自己写这部分的WSDL文档的XSD,你有意见你的服务的WSDL生成器可以理解的方式。
我的框架使用下面的注释语法,包括类型信息:
方法:

/**

 * @param ComplexNumber the first summand

 * @param ComplexNumber the second summand

 * @return ComplexNumber the sum of a and b

 * @access web

 */

function AddTwoComplexNumbers($a, $b) { [...] }

结构复杂:{C}
参数@访问,以确定是否该元素是从境外或没有访问 - 没有此评论的元素不会被公开(出于安全原因)。 @参数名称是可选的,指定使用的WSDL生成的名称。使用框架WsdlBuilder级
当服务的WSDL文档必须生成像上面的例子,的WebserviceInfo级可以使用,否则兼容的一被写入。
class TestWebservice

{

  //include method AddTwoComplexNumbers from example above

}



//include class ComplexNumber from example above



require_once "webserviceInfo.php";



WebserviceRegistry::RegisterWebservice

    ("Test", "TestWebservice"); //"TestWebservice" is the class name of the service

    //"Test" is the actual name used for WSDL-generation



require_once "wsdlBuilder.php";

$builder = new WsdlBuilder

    ("http://www.example.com/myservice"); 	//The URI is the target namespace 

					//of the WSDL-document



require_once "functions.php"; //For GetServerUrl



foreach (WebserviceRegistry::ListWebserviceInfos() 

		as $info) //Add all registered Webservices

  $builder->AddService($info, GetServerUrl() . $_SERVER["SCRIPT_NAME"] . 

		"/service/" . $info->serviceName);

    //The second parameter is the full location where the service can be accessed



$doc = $builder->CreateDocument(); //Create DOM-Document

file_put_contents("services.wsdl", $doc->saveXml());

微小的(静态)WebserviceRegistry类是负责管理服务和创造他们,如果他们需要的。如何WsdlBuilder映射到XSD的类型
的WsdlBuilder内部使用IWsdlTypeMapping的接口类型映射到一个URI。
接口是相当简单:{体C3}
提供接口IWsdlTypeMappingContext的样子:{的C4}
,鉴于AppendToSchema添加自定义的WSDL文档的架构节点れ。可以得到一个新的れ使用GetDoc方法返回主DOMDocument的。的方法GetTypeMapping允许问其他类型的映射器,他们是否可以映射亚型(类型,然后加入过的文件) - 这是需要时,例如:多维数组的映射。确保这不会结束在一个永无止境的递归。
实现的IWsdlTypeMapping接口的对象可以被添加到的WsdlBuilder如下:{C5的}
自定义类型映射器提供的能力,改变方法的参数是由客户端看到的方式。与返回常数WsdlBuilder :: NoMapping它甚至有可能隐藏在WSDL描述的参数 - 在下一章连接,这是一个相当有趣的选项。预处理和后处理通过代理{S0的}
为了避免SoapServer,anbsp的缺点;代理可以使用之前编辑的值作为参数调用的方法,并作为结果返回后,但在此之前发送到客户端传递。这给增强功能,例如,一个DateTime对象可以被转换成SOAP的客​​户了解作为结果传递时的表示。使用的WebserviceProxy级
从技术上讲,代理截获SOAP服务器和服务对象之间的流量控制。{5233}
从服务器调用被重定向到服务代理。
代理从客户端的值转换到PHP的本地对象(如DateTime值)和值从服务到客户端可以理解的表示。自定义转换器
写一个自定义的转换,只需执行的IObjectConverter界面:{C7-}
上下文看起来像:{C8的}
这允许嵌套类型的工作时,这是很重要的问其他的转换器。
确保这不会结束在一个永无止境的递归。服务注册
如果提供多种服务,他们必须举办。为此,静态ServiceRegistry级负责。
它的使用非常简单:
require_once "webserviceInfo.php";



require_once "test.php";

WebserviceRegistry::RegisterWebservice

	("Test", "TestWebservice"); //Register a webservice-class



$service = WebserviceRegistry::GetWebservice("Test"); //Instantiates the webservice-class



WebserviceRegistry::ListWebserviceInfos(); //Returns WebserviceInfo[]
认证
有几个途径来实现身份验证。我建议你​​使用HTTP基本认证,因为它很容易与WCF(Windows通信基础)工作得很好,所以我会解释这一个。
验证,客户端发送的每个请求的两条信息:用户名,将被存放在$ _SERVER ["PHP_AUTH_USERquot;,和密码,将存储在$ _SERVER [quot; PHP_AUTH_PWquot; 。检查前处理SOAP请求。
信号的凭据丢失或错误的(或一般需要身份验证),只需发送下面的标题:{C10的}
境界描述这是保护的部分,它可以自由选择。
不幸的是,用户名和密码发送纯文本,因此,如果他们要加密使用SSL。
当使用基本HTTP-Authenication,WCF需要启用SSL。如何将转入大数据
非法字符的二进制数据或数据传输的SOAP提供的DIME(直接因特网消息封装),默认的PHP SoapServer和WCF不支持。尽管这样,得到的反馈或上传进度,你必须要真正做很多工作。
另一种方法是使用Base64编码的数据,但即便如此,有一些缺点:
这是很慢,数据被炸毁和转让进展的反馈是非常困难的。
那么,为什么不旁边一个单独的原始HTTP请求的SOAP消息传输的数据?这些数据需要进行编码和实施进度的反馈是很容易的,因为它是默认的HTTP请求,并使用SOAP无关。
让我们说,我们有以下方法:{C11的}
将返回的数据传输活动图的样子:{S}返回值是一些关键的一种,获得真实的数据,告诉客户端在某种数据库或硬盘驱动器的磁盘保存二进制数据(关键)(在SOAP调用)返回的数据,而不是指向数据库进入一个关键提供了一个脚本(非SOAP)客户端可以在那里获得通过关键数据删除数据库中的数据
从客户端上传的数据流不有所不同:告诉客户端,参数类型是一些关键的(可以通过上传数据获得)提供(SOAP)的Web服务,它返回(像一个上传票)这样一个关键提供(非SOAP)脚本在客户端可以通过关键数据上传,保存在​​数据库中的数据(关键)当客户端调用(SOAP)的方法,用这把钥匙替换的数据存储在数据库中的关键删除数据库中的数据
接口IWsdlTypeMapping第一步,要实现这样的数据类型将被映射到关键。
由于"stringquot;已经映射到quot; XSD:stringquot的,数据类型,必须改变以quot; binaryquot;或别的东西("的回报binaryquot;或quot; @的参数binaryquot ;) 。
从1-5中的步骤可以通过一个对象,它实现的IObjectConverter接口。
转换方法可以下载数据,上传数据的ConvertBack方法步骤4执行步骤2和3。
建议,包括关键的一个完整的URL,使客户端只到这个网址下载或上传数据的获取。
之下提到的优势,客户可以一次上传多个数据(需要几个方法调用),也许ZIP压缩的加快转移。
编写代码有乐趣!
说实话,我已经写了这样的扩展,但它需要我的容器和高速缓存的框架,我仍然没有公布。 nethertheless,它可以下载{A3的}以上。例子
例如被划分成几个文件:index.php的切入点,security.php包含安全类,这是负责验证和soap.php包含类SoapWebserviceResponse和SoapWsdlResponse负责处理SOAP请求和WSDL检索。
我认为这个例子是足够的评论被理解,没有进一步解释。客户端在C#
编写一个SOAP客户端在C#是很容易的,感谢WCF和Visual Studio。首先,创建1Ç#新项目,可取1控制台应用程序在解决方案资源管理器
右单击quot; Referencesquot;,然后quot;添加网络Referencequot;。
插入的URL的WSDL中的文件(为给定的例子,http://path_to_script/index.php/services.w​​sdl),并单击"Goquot;,现在的Visual Studio解析WSDL文件,并列出找到的所有的服务和他们的方法。一个有意义的名字,并给予参考点击quot;添加Referencequot;认证
正如我在较早,WCF支持HTTP基本身份验证。为了实现这一目标,在Solution Explorer中的app.config文件。
编辑安全节点,所以它看起来像:{C12的}
的境界,是在响应头(见第一章{A5的})相同。
创建客户端后,必须设置凭据:
client.ClientCredentials.UserName.UserName = "user";

client.ClientCredentials.UserName.Password = "password";

重要说明:WCF需要启用SSL(HTTPS的HTTP而不是)!
如果你的证书是无效的,可以使用下面的代码片段来禁用验证检查:
private static bool ValidateRemoteCertificate(object sender,

  X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors)

{

  return true;

}

[...]

ServicePointManager.ServerCertificateValidationCallback += ValidateRemoteCertificate;
扩展点
下面的下面所提到的可能的扩展,可以实现过:Ajax的访问
Web服务可以使用JavaScript访问。Base64编码的支持
类型quot; base64quot;可以自动解码,预处理和后处理编码。增强的安全性
安全检查,可以根据所谓的方法和服务代理。历史版本1.1 - 修正了一些拼写错误版本1.0 - 最初的文章

回答

评论会员:游客 时间:2012/02/06
my_name_4711:致命错误:未定义的类常量的"WsdlTypeMappings"上线204wsdlBuilder.php自我::WsdlTypeMappings的替换:自::$WsdlTypeMappings感谢这个伟大的工具......
亨宁Dieterichs:谢谢你为你的错误报告|
有趣的,我没有注意到这个语法错误,我想我已经测试这段代码之前立即上传...

但也许我会离开它保留了所有的复制和粘贴的孩子{S2的}
如果您发现拼写或语法的错误,请让我知道,这样我就可以纠正他们(至少对我来说) - 英语不是我的第一语言...
评论会员:MrRotzi 时间:2012/02/06
伟大的工作! {S2的}
但我不知道为什么它不可能与VS 2010中创建代理客户的Silverlight {S4}

任何想法
评论会员:亨宁Dieterichs 时间:2012/02/06

是什么问题?原则上,它应该工作(我搜索了一下,整个{A6的}来 - 但我没有看到任何分歧,我的描述)。
如果您发现拼写或语法的错误,请让我知道,这样我就可以纠正他们(至少对我来说) - 英语不是我的第一语言...
:4320844 |会员:感谢对这一惊人PHP SOAP的WebServices的执行