Laravel的中大型项目构架和优雅的插件扩展l5-repository
此篇为转载文章,整理和加入了自己的理解。更建议大家阅读此文,文章很有深度,请你细心阅读,肯定有所收获
目录
(1)前言:
每个程序员对MVC都是必须掌握其思想的。它是一种项目机构的概念。MVC模式它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务。
而Laravel的初级开发者分成两种,(1)是乖乖的将程序填入MVC构架内,导致controller与model异常的臃肿难读,缺乏可读性和可维护性;(2)是常常不知道程序该写在哪一个class内而犹豫不决,毕竟传统PHP都是一个页面一个档案。本文整理出最适合Laravel的中大型项目构架,兼具容易维护、容易扩充与容易重复使用的特点,并且容易测试。
(2)Controller过于肥大:
初学者常认为MVC构架就是model,view,controller:
- Model就是数据库。
- Controller负责与HTTP沟通,调用model与view。
- View就是HTML。
假如依照这个定义,以下这些需求该写在哪里呢?
- 发送Email,使用外部API。
- 使用PHP写的逻辑。
- 依需求将显示格式作转换。
- 依需求是否显示某些数据。
- 依需求显示不同数据。
其中1,2属于商业逻辑,而3,4,5属于显示逻辑,若依照一般人对MVC的定义,model是数据库,而view又是HTML,以上这些需求都不能写在model与view,只能勉强写在controller。
因此初学者开始将大量程序写在controller,造成controller的肥大难以维护。
(3)Model过于肥大:
既然逻辑写在controller不方便维护,那我将逻辑都写在model就好了?
当你将逻辑从controller搬到model后,虽然controller变瘦了,但却肥了model,model从原本代表数据库,现在变成还要负担商业逻辑与显示逻辑,结果更惨。
Model代表数据库吗?把它想成是Eloquent class就好,数据库逻辑应该写在repository里,这也是为什么Laravel 5已经没有models目录,Eloquent class仅仅是放在app根目录下而已。
(4)中大型项目构架:
那我们该怎么写呢?别将我们的思维局限在MVC内:
Model:仅当成Eloquent class。
Repository:辅助model,处理数据库逻辑,然后注入到service。
Service:辅助controller,处理商业逻辑,然后注入到controller。
Controller:接收HTTP request,调用其他service。
Presenter:处理显示逻辑,然后注入到view。
View:使用blade将数据binding到HTML。
其中蓝色为原本的MVC,而紫色为本文要介绍的的重点:Repository模式,Service模式与Presenter模式。
箭头表示物件依赖注入的方向。
我们可以发现MVC构架还在,由于SOLID的单一职责原则与依赖反转原则:
- 我们将数据库逻辑从model分离出来,由repository辅助model,将model依赖注入进repository。
- 我们将商业逻辑从controller分离出来,由service辅助controller,将service依赖注入进controller。
我们将显示逻辑从view分离出来,由presenter辅助view,将presenter依赖注入进view。
(4-1)建立目录
在 app 目录建立 Repositories,Services 与 Presenters 目录。
别害怕在Laravel预设目录以外建立的其他目录,根据SOLID的单一职责原则,class功能越多,责任也越多,因此越违反单一职责原则,所以你应该将你的程序分割成更小的部分,每个部分都有它专属的功能,而不是一个class功能包山包海,也就是所谓的万能类别,所以整个项目不应该只有MVC三个部分,放手根据你的需求建立适当的目录,并将适当的class放到该目录下,只要我们的class有namespace帮我们分类即可。
由于篇幅的关系,将repository独立成专文讨论,请参考如何使用Repository模式?
由于篇幅的关系,将service独立成专文讨论,请参考如何使用Service模式?
由于篇幅的关系,将presenter独立成专文讨论,请参考如何使用Presenter模式?
由于现在model、view、controller的相依物件都已经拆开,也都使用依赖注入,因此每个部分都可以单独的做单元测试,如要测试service,就将repository加以mock,也可以将其他service加以mock。
Presenter也可以单独跑单元测试,将其他service加以mock,不一定要跑验收测试才能测显示逻辑。
(4-2)Conclusion
本文谈到的构架只是开始,你可以依照实际需求增加更多的目录与class,当你发现你的MVC违反SOLID原则时,就大胆的将class从MVC拆开重构,然后依照以下手法:
- 建立新的class或interface。
- 将相依物件依赖注入到class。
- 在class内处理他的职责。
- 将class或interface注入到controller或view。
最后搭配单元测试,测试重构后的构架是否与原来的需求结果相同。
此文翻译于点灯坊,点击查看原文
转载并整理自:http://www.sangeng.org/blog/detail_517.html
(5)l5-repository:
l5-repository是基于以上理念。用于抽象数据层,使我们的应用程序更易于维护.
官网:https://packagist.org/packages/prettus/l5-repository
github地址:https://github.com/andersao/l5-repository
用法和一些注意点我会在laravel5.7加入l5-repository为大家说明。