当前位置: 首页 > 后端技术 > PHP

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

时间:2023-03-30 06:15:40 PHP

当我们谈到应用的架构时,经常会问到一个经典的问题,那就是“这段代码应该放在哪里?”。因为Laravel是一个相当灵活的框架,所以要回答这个问题并不容易。我应该在模型层、控制器层还是其他地方编写我的业务逻辑?当你的应用只有一个接入点时,把业务逻辑写在Controller层是没问题的。但是现在更常见的是有很多接入点调用同一个功能模块。比如太多的应用都有用户注册的功能,它的过程就是调用一个controller,然后返回一个注册成功或者失败的视图。如果这个应用也有移动端,它很可能会提供一套用于移动端用户注册的API,因为它需要返回的数据格式是JSON。使用Laravel的artisan命令创建用户也很常见,尤其是在项目的早期开发阶段。上面两段代码看似没有问题,但是随着业务逻辑的增加,代码会显得非常冗余。例如,如果需要在新用户注册后添加给用户发送邮件通知的功能,则必须在上述两个控制器中添加发送邮件的代码。但是如果我们想保持代码的简洁和优雅,我们可以把这些业务逻辑写在别处。对于“业务逻辑代码写在哪里”的问题,在任何一个论坛上都能得到一个笼统的回答,那就是“使用一个service层,然后在controller层调用这个service类”。对,没错,问题是我们应该如何设计服务类呢?是不是创建一个UserService类来实现所有与用户相关的业务逻辑,然后将这个类注入到需要使用的Controller层?或者还有其他选择吗?避免类神的陷阱首先,尝试为包含所有代码的特定模型创建一个类。例如:它看起来很完美:我们可以在任何控制器中声明或使用创建/删除方法并获得我们想要的结果。但是这个实现有什么问题呢?即我们通常在解决问题的过程中很少使用单一模型。例如,当我们为用户创建一个帐户时,我们同时也为该用户创建了一个单独的博客。要以目前的方式实现这个过程,我们必须创建一个BlogService类,然后将其依赖项注入到UserService类中。显然,随着应用业务的增长,会有几十到上百个服务类,其中一些服务类需要依赖5到6个其他服务类,最终造成代码冗余和混乱的情况,这是我们要避免的不惜一切代价。引入单一操作类那么,我们决定将其拆分为多少个类,而不是使用具有多个方法的单个服务类?下面是我最近在每个项目中使用的方法,效果很好,推荐给大家。首先,让我们摒弃过于笼统和模糊的服务术语,看看我们的新操作类并定义它们是什么以及它们可以做什么。一个动作类应该有一个能够说明其功能的名称,例如:CreateOrder、ConfirmCheckout、DeleteProduct、AddProductToCart等,它应该有一个且只有一个公共方法,作为API。理想情况下,它应该是相同的方法名称,例如handle()或execute()。如果我们需要为我们的操作类实现某种适配器模式,这将非常方便。它必须与请求和响应无关。它不处理请求,也不发送响应。这种责任应由控制者承担。它可以依赖于其他动作类。如果有任何事情阻止它执行和/或返回预期值,那么它必须通过抛出异常来强制执行相关的业务逻辑,并让调用者(或Laravel的ExceptionHandler)负责如何呈现/响应异常。创建我们的CreateUser操作类现在,让我们以前面的示例为例,并使用我们将其命名为CreateUser的单个操作类重构它。您可能想知道为什么当电子邮件地址已被使用时此方法会抛出异常。这不是通过请求验证来保证的吗?当然。但是,在动作类内部执行业务逻辑不是更好吗?这使得逻辑易于理解和调试。我们来看一下使用我们的action类后的controller代码,如下:现在,无论我们做什么改动,用户注册过程都将由API和网页版处理,优雅而利落。动作类的嵌套假设我们需要一个动作类来将1000个用户导入到我们的应用程序中。我们可以编写一个动作类并继续使用上面的CreateUser类:非常简洁,不是吗?我们可以通过将CreateUser代码嵌入到Collection::map()方法中来重用它,然后返回所有新创建的用户的集合。当邮件被占用的时候,我们可以返回NullObject或者记录在Log文件中,大家应该已经想到了。动作类的装饰器现在,假设我们要记录每个新注册用户。我们可以把代码写在动作类里面或者使用装饰器模式。然后我们可以使用Laravel的IoC容器将LogCreateUser类绑定到CreateUser类,这样每当我们需要后者的实例时,前者将被注入:AppServiceProvider.php这使得可以使用配置或环境变量来控制日志记录功能它激活或者停用比较方便:AppServiceProvider.php总结使用这个方法好像需要很多类。当然,用户注册只是一个简单的例子,以保持代码简洁明了。一旦项目的复杂性开始增长,动作类的真正价值就会变得越来越明显,因为你清楚地知道代码在哪里,它的边界在哪里。使用单一动作类的好处:小而单一的逻辑域可以防止代码重复并提高代码的可重用性,保持代码的稳定性。易于独立测试各种场景。有意义的命名在较大的项目中更容易阅读。易于装饰。Consistencyacrosstheproject:防止代码分布在Controller、Model等之间。当然,这种方法是基于我这几年使用Laravel的一些经验,以及我在一些项目中的实践。这对我来说真的很管用,现在我什至在一些中小型项目中使用它。如果您有不同的方法,我非常期待阅读它。如需更多现代PHP知识,请访问Laravel/PHP知识社区