设为首页 收藏本站
查看: 692|回复: 0

[经验分享] 拙议REST及其在PHP中的现状

[复制链接]
发表于 2017-4-10 08:25:57 | 显示全部楼层 |阅读模式
  HTTP被发明出来的时候,其实REST就已经存在了。可惜这么多年来,WEB开发模式却越来越背离HTTP的本质,舍本逐末的追求起RPC之类的东西。此时REST重新回到人们的视线里,无疑让大家开始反思过去走过的弯路。

本文并不想从头介绍REST,只是想举例说明一下需要注意的问题:

先来看看人们对REST的困惑:

REST长啥样?

最一般的REST例子,类似下面的样子:
  

POST   /articles     创建

DELETE /articles/123 删除

PUT    /articles/123 更新或创建

GET    /articles/123 查看
  

顺便说说几个知识点:

GET操作是安全的。所谓安全是指不管进行多少次操作,资源的状态都不会改变。比如我用GET浏览文章,不管浏览多少次,那篇文章还在那,没有变化。当
然,你可能说每浏览一次文章,文章的浏览数就加一,这不也改变了资源的状态么?这并不矛盾,因为这个改变不是GET操作引起的,而是用户自己设定的服务端
逻辑造成的。

PUT,DELETE操作是幂等的。所谓幂等是指不管进行多少次操作,结果都一样。比如我用PUT修改一篇文章,然后在做同样的操作,每次操作后的结果并没有不同,DELETE也是一样。顺便说一句,因为GET操作是安全的,所以它自然也是幂等的。

POST操作既不是安全的,也不是幂等的,比如常见的POST重复加载问题:当我们多次发出同样的POST请求后,其结果是创建出了若干的资源。

安全和幂等的意义在于:当操作没有达到预期的目标时,我们可以不停的重试,而不会对资源产生副作用。从这个意义上说,POST操作往往是有害的,但很多时候我们还是不得不使用它。

还有一点需要注意的就是,创建操作可以使用POST,也可以使用PUT,区别在于POST
是作用在一个集合资源之上的(/articles),而PUT操作是作用在一个具体资源之上的(/articles/123),再通俗点说,如果URL可
以在客户端确定,那么就使用PUT,如果是在服务端确定,那么就使用POST,比如说很多资源使用数据库自增主键作为标识信息,而创建的资源的标识信息到
底是什么只能由服务端提供,这个时候就必须使用POST。

浏览器不支持PUT/DELETE方法怎么办?

大部分浏览器只支持GET/POST方法,这使得我们无法完美的实现REST。对于这样的情况,大致有几种解决方法,一种是在表单里加入一个
_method之类名字的隐藏字段,用于表示真正的方法,另一种是使用X-HTTP-METHOD-OVERRIDE头信息来重载POST。

HTTP方法够用么?

从上面的例子,我们可以看到,通过使用已有的HTTP方法:POST,DELETE,PUT,
GET就可以完成资源的增删改查,但在实际情况中,我们需要做的操作往往并不仅仅局限在简单的增删改查操作中,比如说我们要把一篇文章“置顶”,但是
HTTP方法里没有一个和“
置顶”操作相对应的方法,这时候该怎么办呢?REST对类似问题的解决方案是:创建一个新的资源!在上面的例子里,我们可以这样:

PUT /toparticles/123

通过创建出一个新的资源(toparticles),我们就可以使用简单的HTTP方法通吃一切操作了。


REST反对使用Session 么?

牢记一点,REST拒绝Session!这是因为REST强调无状态性。这里的状态指的的应用状态,也可以称之为会话状态。一旦在服务端保持了这样的状态,那么架构的可扩展性将大打折扣。在REST看来,任何类似的状态本身都应该是一个独立的资源。

Cookie对REST有害么?

一分为二的看,如果Cookie里保存的是应用状态的话,就没有问题。因为应用状态本来就属于客户端。但如果使用Cookie保存类似PHPSESSIONID之类的东西就不对了,因为这样的数据并不属于客户端状态,它只不过是使用Session的借口而已。

再来看看REST在PHP中的现状:

PHP里的REST实现案例不多,有点影响都就是CakePHP和Zend,下面分别看看他们的实现:

CakePHP:

设定路由:

Router::parseExtensions ('xml');

Router::mapResources('articles');

编写控制器:

class ArticlesController extends AppController {     var $components = array('RequestHandler');
function view($id = null) {
$article = $this->Article->findById ($id);
$this->set(compact ('article'));
}
// ...
}
   视图:


<articles>
<?php echo $xml->serialize($article); ? >
</articles>
  
差不多就这样了,相应的,还可以实现其他的功能,于是,如下REST操作便成为可能:

POST   /articles

DELETE /articles/123.xml

PUT    /articles/123.xml

GET    /articles/123.xml

总体看,CakePHP的REST实现基本上是按Rails风格来实现的,大体还过得去。

参考链接:
http://book.cakephp.org/view/476/rest

http://c7y.phparch.com/c/entry/1/art
,cakephp- rest


ZendFramework:

ZendFramework通过Zend_Rest组件来实现Rest功能:

服务端:

require_once 'Zend/Rest/Server.php'; function sayHello($who, $when)
{
return "Hello $who, Good $when";
}
$server = new Zend_Rest_Server();
$server->addFunction('sayHello');
$server- >handle();
   客户端:

require_once 'Zend/Rest/Client.php'; $client = new Zend_Rest_Client('http://path/to/server/script');
$client- >
sayHello('Davey', 'Day');
  |lt;br /> echo $client->get ();
  

这时候,我们看一下Web服务器的日志,会发现生成了一条如下的记录:

GET /path/to/servier/script?method=sayHello&arg0=Davey&arg1=Day&rest=1 HTTP/1.1

我们发现,实际操作方法是由URL中的method=sayHello指定的,而HTTP固有方法(GET/POST等)则成为了摆设,这是典型的RPC
风格,如果大家对比Zend_Rest和 Zend_XmlRpc文档的话,会明显发现它们根本就是一个东西,所以说,Zend_Rest是一个
REST伪实现。

参考链接:
http://framework.zend.com/manual/en/zend.rest.html

http://framework.zend.com/manual/en/zend.xmlrpc.html

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-362650-1-1.html 上篇帖子: PHP建设论坛:Discuz!论坛快速架设指南 下篇帖子: CKEditor安装与配置(PHP)FCKEditor在线编辑器
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表