Whip Monstrous Code Into Shape 16-Staying True to the Seven Resourceful Methods

In this monstrous code episode, we'll review one technique to help keep your controllers in check. Have you ever created a resourceful controller, but found yourself, over time, adding more and more actions to it? It starts to get pretty bloated, right? Well what if, instead, you took that non-resourceful action and extracted it its a new controller? What might that look like?


第15节讲的是用之前的方法重构的一个例子,没什么新东西,跳过。

这节视频讲的是如何更好的使用 resourceful controller。

Laravel 里面的 resourceful controller 包含 7个最基本的方法:index, show, create, store, edit, update, destroy。项目开始的时候一般这几个方法足够用了,但是随着项目的进行,越来越多的功能加了进来,控制器中的方法也逐渐增多,很多动作也不是这7个方法能满足的。

比如有个FlightsController

// FightsController
    // GET /fights          => 所有的航班
    // GET /fights/{id}     => 查看航班
    // create, store, edit, destroy
    // UPDATE /fights/{id}  => 更新航班

如果添加查看取消的航班的功能,一个做法是在 index 动作上添加一个 uri query:

// GET /fights?canceled=true

另外一个做法是添加一个对应的路由,控制器中也添加一个相应的方法。

// GET /fights/canceled => FightsController@canceled

在这种情况比较少的时候可以采用,但是现实情况可能更复杂。比如一个订单,除了正常的 7 个动作,可能会有激活、取消、审批、付款、完成等很多的状态,每种状态可能又有查看、完成、取消、退回等等不同的操作。按照上面这种方法,控制器不可避免的会变得越来越复杂。

在这种情况下,可能要考虑把这些情况从一个共有的控制器中分离到单独的控制器中。比如上面这个情形,可以把取消的航班从航班控制器中分离出来,创建一个新的 CanceledFlightsController,而这个控制器也可以继续延续 resourceful controller 风格,比如查看所有的取消的航班,添加新的取消航班等等。

// GET  /fights/canceled        => CanceledFlightsController@index
// POST /fights/canceled/{id}   => CanceledFlightsController@store

再看看一个例子。

比如有个 conversation 模型,对应的有个 resource Controller ConversationsController。有个订阅列表,用户可以订阅这个 conversation。

// ConversationsController
    // index, show, create, store, edit, update, destroy

    // POST  /conversations/{id}/subscribe_to        => ConversationsController@addSubscriber

这个时候考虑把这个订阅动作放到新的控制器中 ConversationsSubscriptionsController

// POST  /conversations/{id}/subscription        => ConversationsSubscriptionsController@store

这个时候再看看 uri 和 控制器,如果再要添加修改订阅、删除订阅的话,uri 就会像这样嵌套下去:

// GET  /conversations/{id}/subscription/{id}        => ConversationsSubscriptionsController@show
// DESTROY  /conversations/{id}/subscription/{id}      => ConversationsSubscriptionsController@destroy

这个时候可以把 subscription 当作一个资源,控制器和 uri 这样写会简洁不少。

// POST  /subscription              => SubscriptionsController@store {conversation_id = 1}
// GET  /subscription/{id}          => SubscriptionsController@show
// DESTROY  /subscription/{id}      => SubscriptionsController@destroy

之前在写 restful 风格的 api,看了一篇文章,讲的是设计restful风格的 uri 和 动作,貌似找不到原文了,大概表述一下作者的意思。作者在开头说了个问题,就是有些人很抵触 restful 风格的设计,觉得把所有的 uri 当作资源不是很合理,比如如何定义一个用户登录?是用 POST or PATCH or PUT? 如何当作一个资源?作者的看法是,登录一个用户,实际是创建一个 session 或者 创建一个 token,所以应该使用 POST,uri 设计也应该是 '/session' 或者 '/token'。再比如激活一个用户,可以把激活的用户当作一个资源,而激活用户则是创建一个激活的用户,所以应该用 post 而不是 put or pathc;相对的取消激活一个用户相当于从激活用户里面删除一个用户,所以应该用 destroy。

看了这篇文章后我觉得很有意思,倒不是说非得按照作者的意思把一切都当作资源用 restful 风格来写,很多情况下可以参考,确实对自己的思维有个很大的扩展,很多东西不是非黑即白,而是有无限种可能。

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 3
nickfan

其实这种url规则起名对于规则洁癖的人很纠结~~~
另外 laravel的路由用preg_match,有32字符限制也是蛮坑的,
正则限制,没办法。

PCRE sub-patterns cannot be longer than 32 characters, 

具体见:https://github.com/laravel/framework/issue...

7年前 评论

@nickfan 我工作中就碰到嵌套的路由,尤其是碰到那种一对多关系的时候写一长串,我觉得没有必要 而且经常父id 根本就没什么作用,但是不得不传到控制器中

7年前 评论

@nickfan 还有有32字符限制呢,不过没用那么长的

7年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!