Laravel 程序架构设计思路:使用动做类

file

当咱们谈论到应用程序的架构的时候,常常会问到一个经典的问题,那就是“这段代码应该放在哪里比较好”。 由于 Laravel 是一个至关灵活的框架,因此要回答这个问题其实没那么容易。我应该把个人业务逻辑写在 Model 层,仍是 Controller 层,或者是其余地方?php

当你的应用程序仅有一个接入点,把业务逻辑写在 Controller 层是能够的。可是如今更广泛的的情形是,有不少接入点去调用相同的功能模块。laravel

好比说,太多数的应用程序都有用户注册的功能,它的流程是调用一个控制器而后返回一个注册成功或者失败的视图。假如这个应用程序还有移动端,那就极可能要提供一套针对移动端用户注册的 API ,由于它须要返回的数据格式是 JSON 。并且利用 Laravel 的 artisan 命令来建立用户也很常见,尤为是在项目前期的开发阶段。架构

file

上面这两段代码可能看起来没有什么问题的,可是,随着业务逻辑的增长,就会显得代码很冗余。举个例子,若是你须要新用户注册完以后,增长给用户发送邮件通知的功能,你必需要再上面两个控制器中都添加发送邮件的代码。可是若是要保持代码的简洁优雅,咱们能够把这些业务逻辑写到其余地方。框架

对于“把业务逻辑代码写到哪里”的这个问题,你去任何论坛均可以获得一个广泛的答案,那就是 “使用一个 service 层,而后在 controller 层调用这个服务类”。是的,没错,问题是咱们应该怎么设计 service 类?是建立一个 UserService 类来实现全部跟用户用户有关的业务逻辑,而后把这个类注入到须要用到的 Controller 层?或者是还有其余方案?ide

避免神类的坑

首先,能够尝试为一个特定的模型建立一个单一类,其中包含全部的代码。例如:测试

file

看起来很完美:咱们能够任何控制器中申明或者使用 create/delete 方法,而且获得咱们想要的结果。可是,这种实现有什么问题呢? 那就是咱们在解决问题的过程一般不多使用单一的模型 设计

好比说,当咱们给一个用户建立了帐号的时候,也要同时给用户单首创建一个 blog 。若是按照当前的方式去实现这个流程,咱们就必须建立一个 BlogService 类,而后将其依赖注入到 UserService 类。调试

file

显而易见,随着应用程序的业务的增加,将会有几十到上百个 service 类,其中的一些 service 类须要依赖 5 到 6 个其余 service 类,最终的结果就是,出现代码的冗余跟混乱的局面,而这个局面是咱们想不惜一切代价去避免的。日志

介绍单动做类

那么,若是不是用一个单一的服务类加上几个方法,咱们决定把它分红几个类?下面是我最近每个项目都采用的方法,结果很不错,推荐给你们。code

首先,让咱们抛弃过于笼统和模糊的服务术语,来了解一下咱们的新动做类,并定义它们是什么以及它们能够作什么。

  • 一个动做类,应该有一个可以说明其功能的名字,好比:CreateOrder, ConfirmCheckout, DeleteProduct, AddProductToCart等。
  • 它应该有且只有一个公共方法,做为 API 。理想的状况下,应该是相同的方法名,像 handle() 或者 execute() 。若是须要对咱们的动做类实现某种适配器模式,这是很是方便的。
  • 它必须对请求和响应不可知。它不处理请求,也不发送响应。这样的职责应该由控制器来承担。
  • 它能够依赖其它的动做类。
  • 若是有任何事情阻止它执行和/或返回指望的值,那么它必须经过抛出一个 Exception 来强制执行相关的业务逻辑,而且让调用者(或者 Laravel 的 ExceptionHandler )来承担如何呈现/响应异常的责任。

建立咱们的 CreateUser 动做类

如今,让咱们看看前面的例子,并用一个单动做类来重构它,咱们将命名为 CreateUser 。

file

你或许想知道当邮箱地址已经被占用时,该方法为何会抛出了异常。 这难道不是请求验证来保证的吗?固然能够。然而,在动做类内部来执行业务逻辑不是更好吗?这样使得逻辑变得易于理解和调试。

让咱们看看使用咱们动做类以后的控制器代码,以下:

file

如今,不管咱们作什么修改,用户注册过程都会由 API 和 Web 版本处理,优雅整洁。

动做类的嵌套

假如,咱们须要一个动做类将 1000 个用户导入咱们的应用中。咱们能够写一个动做类,而且继续使用上文的 CreateUser 类:

file

很是整洁,不是吗?咱们能够经过将其嵌入在 Collection::map() 方法中来重用 CreateUser 代码,而后返回全部新建用户的集合。当邮件被占用的时候,咱们能够经过返回 Null Object 或者在 Log 文件中记录一下,你应该已经想到了。

动做类的装饰

如今,假设咱们想在日志中记录每个新注册的用户。咱们能够将代码写在动做类内部,也可使用装饰者模式。

file

而后,咱们可使用 Laravel 的 IoC 容器将 LogCreateUser 类绑定到 CreateUser 类,全部每当咱们须要一个后者的实例时,前者都会注入进来:

file

AppServiceProvider.php

这使得使用配置或环境变量来控制日志记录功能的激活或停用更为方便:

file

AppServiceProvider.php

总结

使用这个方法彷佛会须要不少的类。固然,用户注册仅仅是一个简单的例子,旨在保证代码的简短清晰。一旦项目的复杂度开始增加,动做类的真正的价值就愈来愈明显,由于你清晰的知道代码所在及其界定。

使用单动做类的好处:

  • 小巧而单一的逻辑域可以防止代码重复并提升代码的可重用性,保持稳定。
  • 易于针对各类场景进行独立测试。
  • 富有意义的命名在大型项目中更容易阅读。
  • 易于装饰。
  • 整个项目的一致性:防止代码分布在 Controllers、Models 等。

固然,这个方法是基于我过去几年使用 Laravel 的一些经验和我在一些项目中的实践。这对我真的颇有用,如今我甚至在一些中小型项目中使用。

若是你有不一样的方法,我很是期待读一读。

更多现代化 PHP 知识,请前往 Laravel / PHP 知识社区

相关文章
相关标签/搜索