免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2094 | 回复: 0
打印 上一主题 下一主题

PHP Cookbook读书笔记 – 第15章创建Web服务 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-11-22 16:58 |只看该作者 |倒序浏览
本帖最后由 听老歌 于 2011-11-22 17:03 编辑

PHP Cookbook读书笔记 – 第15章创建Web服务






实现一个REST的WEB服务
实现一个REST的web服务相对还是比较简单的,用到了HTTP的GET、POST、PUT、DELETE特性。其PHP的处理代码和普通处理POST和GET十分相似

view sourceprint?
  1. 01 // 转换到大写  

  2. 02 $request_method = strtoupper($_SERVER['REQUEST_METHOD']);  

  3. 03   

  4. 04 switch ($request_method) {  

  5. 05 case 'GET':  

  6. 06     $action = 'search';  

  7. 07     break;  

  8. 08 case 'POST':  

  9. 09     $action = 'add';  

  10. 10     break;  

  11. 11 case 'PUT':  

  12. 12     $action = 'update';  

  13. 13     break;  

  14. 14 case 'DELETE':  

  15. 15     $action = 'delete';  

  16. 16     break;  

  17. 17 default:  

  18. 18     // 无效的动作  

  19. 19     exit();  

  20. 20 }  

  21. 21 //处理完返回XML格式或Json等格式的结果
复制代码
这段代码就是对4种不同的请求进行处理,SQL与REST的对应关系可以看下表
  1. SQL REST
  2. CREATE POST
  3. SELECT GET
  4. UPDATE PUT
  5. DELETE DELETE
复制代码
对于需要授权的访问在rest中如何实现,书中并没有提及。现在很多开放API都是需要授权后才能使用的,它的实现原理是每次请求时需要携带一个额外的参数,这个参数就是经过加密的验证授权信息的。
以SOAP方式提供数据
使用ext/soap的SOAPServer类实现不带WSDL的WEB服务,你会发现SOAPServer来搭建WEB服务和写PHP的普通类差别并不大(当然也可以用函数),就是在实例化一个SOAPServer时将类名什么的与之关联,下面是一个简单的例子

view sourceprint?
  1. 1 class pc_SOAP_return_time {  

  2. 2     public function return_time() {  

  3. 3         return date('Ymd\THis');  

  4. 4     }  

  5. 5 }  

  6. 6   

  7. 7 $server = new SOAPServer(null, array('uri'=>'urn:pc_SOAP_return_time'));  

  8. 8 $server->setClass('pc_SOAP_return_time');  

  9. 9 $server->handle();
复制代码
客户端调用服务的代码如下:

view sourceprint?
  1. 1 $opts = array('location' => 'http://api.example.org/getTime',  

  2. 2               'uri' => 'urn:pc_SOAP_return_time');  

  3. 3 $client = new SOAPClient(null, $opts);  

  4. 4 $result = $client->__soapCall('return_time', array());  

  5. 5 print "The local time is $result.\n";
复制代码
用函数来处理的书中也有做介绍,因为我满脑子OO,就省略了。

如果客户端调用一个服务端不存在的方法时,服务器会以一个SOAP故障作为应答,如果希望控制应答的内容,可以通过__call()方法来实现,如下面代码所示:

view sourceprint?
  1. 01 class pc_SOAP_Process_All_Methods {  

  2. 02   

  3. 03     // Handle any undefined methods here  

  4. 04     public function __call($name, $args) {  

  5. 05         // ...  

  6. 06     }  

  7. 07 }  

  8. 08   

  9. 09 $server = new SOAPServer(null, array('uri'=>'urn:pc_SOAP_Process_All_Methods'));  

  10. 10 $server->setClass('pc_SOAP_Process_All_Methods');  

  11. 11 $server->handle();
复制代码
在SOAP方法中接受参数
在服务端定义方法是增加参数,然后在客户端调用时SOAPClient->__soapCall('return_time', array(参数数组));是不是很简单,上面的代码各修改1处即可

view sourceprint?
  1. 01 class pc_SOAP_return_time {  

  2. 02 //第一处不同,增加了$tz参数  

  3. 03     public function return_time($tz = '') {  

  4. 04         if ($tz) { $my_tz = date_default_timezone_set($tz); }  

  5. 05         $date = date('Ymd\THis');  

  6. 06         if ($tz) { date_default_timezone_set(ini_get('date.timezone')); }  

  7. 07         return $date;  

  8. 08     }  

  9. 09 }  

  10. 10   

  11. 11 $server = new SOAPServer(null,array('uri'=>'urn:pc_SOAP_return_time'));  

  12. 12 $server->setClass('pc_SOAP_return_time');  

  13. 13 $server->handle();
复制代码
客户端调用
view sourceprint?
  1. 1 $opts = array('location' => 'http://api.example.org/getTime',  

  2. 2               'uri' => 'urn:pc_SOAP_return_time');  

  3. 3 $client = new SOAPClient(null, $opts);  

  4. 4 //第二处不同,将tz设置为奥斯陆  

  5. 5 $result = $client->__soapCall('return_time', array('tz' => 'Europe/Oslo'));  

  6. 6 print "The local time is $result.\n";
复制代码
自动生成WSDL文件
前面已经说了,ext/soap扩展不支持WSDL自动生成功能,可以考虑手工生成WSDL文件(相信大家是不会这么做的),还有就是可以通过下面这几种非官方的脚本来实现,需要注意的是这几种方式都没能完全支持SOAP和WSDL规则,如果要很好的使用需要对它们进行仔细研究

  1. WSDL_Gen, by George Schlossnagle

  2. [url]http://www.schlossnagle.org/~george/blog/index.php?/archives/234-WSDLGeneration.html[/url]

  3. wsdl-writer, by Katy Coe based on code by David Griffin

  4. [url]http://www.djkaty.com/drupal/php-wsdl[/url]

  5. Web service helper, by David Kingma

  6. [url]http://jool.nl/new/[/url]
复制代码
处理SOAP头部信息
当ext/soap发现一个带有SOAP头的客户端请求时,它首先会尝试调用一个具有相同名字的函数。调用完成后,会继续调用在SOAP主体中指定的函数。这样就可以使你基于SOAP头部数据来执行任何预请求的事务。

但是,ext/soap服务器端不会以编程的方式对SOAP头部和主体进行真正的区分。当ext/soap发现一个SOAP头时,它会在处理主体之前尝试调用与该头部元素同名的方法。

如果SOAP客户端指定的头部不存在,ext/soap会跳过该方法直接转到主体中。如果头部中的mustUnderstand 属性标记为true,那么SOAPServer就会放出一个SOAP故障。

view sourceprint?
  1. 01 $opts = array('location' => 'http://api.example.org/getTime',  

  2. 02               'uri' => 'urn:pc_SOAP_return_time');  

  3. 03 $client = new SOAPClient(null, $opts);  

  4. 04 $set_timezone = new SOAPVar('Europe/Oslo', XSD_STRING);  

  5. 05   

  6. 06 //设置SOAP头部  

  7. 07 $tz = new SOAPHeader('urn:pc_SOAP_return_time', 'set_timezone', $set_timezone);  

  8. 08   

  9. 09 $result = $client->__soapCall('return_time', array(), array(), array($tz));  

  10. 10 print "The local time is $result.\n";
复制代码
生成SOAP头信息
view sourceprint?
  1. 01 class pc_SOAP_return_time {  

  2. 02     public function return_time() {  

  3. 03         $tz = date_default_timezone_get();  

  4. 04   

  5. 05         //生成头部信息  

  6. 06         $header = new SoapHeader('urn:pc_SOAP_return_time', 'get_timezone', $tz);  

  7. 07   

  8. 08         $GLOBALS['server']->addSoapHeader($header);  

  9. 09         return date('Ymd\THis');  

  10. 10     }  

  11. 11 }  

  12. 12 $server = new SOAPServer(null, array('uri'=>'urn:pc_SOAP_return_time'));  

  13. 13 $server->setClass('pc_SOAP_return_time');  

  14. 14 $server->handle();
复制代码
由于在方法的作用域中不能轻易地访问到$server对象,需要通过$GLOBALS数组来访问该对象。响应时会包含下面的SOAP头:

view sourceprint?
  1. 1 <SOAP-ENV:HEADER>  

  2. 2 <NS1:GET_TIMEZONE>America/Los Angeles</NS1:GET_TIMEZONE>  

  3. 3 </SOAP-ENV:HEADER>
复制代码
用SOAP头实现验证
因为没有办法强制ext/soap请求SOAP头部信息,所以需要在每个需要验证的方法内添加一个判断语句对pc_authenticate_user进行判断,如果客户端没有通过验证则抛出一个SOAP故障

view sourceprint?
  1. 01 function pc_authenticate_user($username, password) {  

  2. 02     // authenticate user  

  3. 03     $is_valid = true; // Implement your lookup here  

  4. 04   

  5. 05     if ($is_valid) {  

  6. 06         return true;  

  7. 07     } else {  

  8. 08         return false;  

  9. 09     }  

  10. 10 }  

  11. 11   

  12. 12   

  13. 13 class pc_SOAP_return_time {  

  14. 14     private $authenticated;  

  15. 15   

  16. 16     public function __construct() {  

  17. 17         $this->authenticated = false;  

  18. 18     }  

  19. 19   

  20. 20     public function authenticate_user($args) {  

  21. 21         // Throw SOAP fault for invalid username and password combo  

  22. 22         if (! pc_authenticate_user($args->username,  

  23. 23                                    $args->password)) {  

  24. 24   

  25. 25             throw new SOAPFault("Incorrect username and password combination.", 401);  

  26. 26         }  

  27. 27   

  28. 28         $this->authenticated = true;  

  29. 29     }  

  30. 30   

  31. 31     // Rest of SOAP Server methods here...  

  32. 32     public function soap_method() {  

  33. 33         if ($this->authenticated) {  

  34. 34             // Method body here...  

  35. 35         } else {  

  36. 36             throw new SOAPFault("Must pass authenticate_user Header.", 401);  

  37. 37         }  

  38. 38     }  

  39. 39   

  40. 40 }  

  41. 41   

  42. 42 $server = new SOAPServer(null, array('uri'=>'urn:pc_SOAP_return_time'));  

  43. 43 $server->setClass('pc_SOAP_return_time');  

  44. 44   

  45. 45 $server->handle();
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP