我认为,只要遵循
SOLID原则,您提出的所有模式/架构都非常有用。
对于“在哪里添加逻辑”,我认为重要的是参考
单一职责原则。此外,我的答案考虑到您正在开展中型/大型项目。如果这是一个“将某些东西扔在页面上”的项目,请忘记这个答案,并将所有内容添加到控制器或模型中。
简短的回答是:
在有服务的情况下,放在您认为合适的位置。
长答案如下:
控制器:控制器的职责是什么?当然,您可以将所有逻辑放在控制器中,但这是控制器的责任吗?我不这么认为。
对我来说,控制器必须接收请求并返回数据,这不是放置验证、调用数据库方法等的地方。
模型: 这是添加诸如用户注册时发送欢迎电子邮件或更新帖子投票计数等逻辑的好地方吗?如果您需要从代码的另一个位置发送相同的电子邮件,该怎么办?您会创建一个静态方法吗?如果该电子邮件需要另一个模型的信息怎么办?
我认为模型应该代表一个实体。对于 Laravel,我只使用模型类来添加像 fillable
、guarded
、table
和关系之类的东西(这是因为我使用存储库模式,否则模型也将具有 save
、update
、find
等方法)。
存储库(存储库模式): 起初,我对此非常困惑。而且,像您一样,我认为“好吧,我使用 MySQL 就可以了。”
然而,我已平衡使用存储库模式的利弊,并现在使用它。我认为,现在,就在这个时刻,我只需要使用 MySQL。但是,如果三年后我需要更改为类似 MongoDB 的东西,大部分工作都已完成。所有这些都是以额外接口和 $app->bind(«interface», «repository»)
的代价。
事件 (观察者模式): 事件对于可以在任何时间抛出的事情非常有用。例如,想象一下向用户发送通知。当您需要时,您可以触发事件,在应用程序的任何类中发送通知。然后,您可以拥有一个名为UserNotificationEvents
的类来处理所有与用户通知相关的已触发事件。
服务: 目前为止,您可以选择将逻辑添加到控制器或模型中。对于我来说,将逻辑添加到服务中是有意义的。让我们面对现实,服务是一个高级名称,代表类。您可以在应用程序中拥有尽可能多的类,只要对您有意义即可。
举个例子:不久前,我开发了类似Google表单的东西。我从CustomFormService
开始,最终有了CustomFormService
、CustomFormRender
、CustomFieldService
、CustomFieldRender
、CustomAnswerService
和CustomAnswerRender
。为什么?因为这对我来说是有意义的。如果你与一个团队合作,应该把你的逻辑放在对团队有意义的地方。
使用服务(Service)而不是控制器(Controller)/模型(Model)的优势在于,您不受单个控制器或单个模型的限制。根据您的应用程序的设计和需求,可以创建尽可能多的服务。此外,调用服务(Service)的优点是您可以在应用程序的任何类中调用它。
虽然这篇文章很长,但我想向您展示我如何构建我的应用程序:
app/
controllers/
MyCompany/
Composers/
Exceptions/
Models/
Observers/
Sanitizers/
ServiceProviders/
Services/
Validators/
views
(...)
我为每个文件夹指定特定的功能。例如,
Validators
目录包含一个
BaseValidator
类,负责根据特定验证器(通常是每个模型的一个)的规则和消息处理验证。虽然这段代码也可以轻松地放在一个服务中,但对我来说,在服务内使用时有一个专用的文件夹是有意义的(至少现在是这样)。
我建议您阅读以下文章,因为它们可能会更好地解释这些内容:
Breaking the Mold by Dayle Rees(CodeBright 的作者):这是我将所有东西整合在一起的地方,尽管我改变了一些东西以适应我的需求。
Decoupling your code in Laravel using Repositories and Services by Chris Goosey:这篇文章很好地解释了什么是服务和仓库模式以及它们如何结合在一起。
Laracasts还有简化仓库和单一职责原则这两个资源,提供了实用的例子(尽管需要付费)。