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 风格来写,很多情况下可以参考,确实对自己的思维有个很大的扩展,很多东西不是非黑即白,而是有无限种可能。
推荐文章: