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

Laravel深度学习5-应用架构

时间:2023-03-29 16:11:12 PHP

声明:本文非博主原创,而是来自《Laravel 4 From Apprentice to Artisan》阅读的翻译和理解,当然不是原文翻译,能保证90%原创.因为是理解翻译,难免有错误,欢迎指正。欢迎转载,转载请注明出处,谢谢!应用程序架构简介那一章是什么?这对于使用框架创建应用程序非常常见。很多开发者问这个问题是因为他们脑子里已经有了“模型”就是“数据库”的概念。所以一般来说,controller是用来和HTTP交互的,model是跟database对话的部分,view是还有HTML代码的部分。但是,发送邮件、验证数据类、访问接口等类如何区分呢?本章我们将探讨Laravel构建的架构,打破固定在脑海中的概念,让开发回归本质。MVC会杀了你我们的设计障碍之一是:M-V-C。模型、视图、控制器,这种框架思维控制了开发者很多年。这种思想来源于RubyOnRails。如果你要求程序员解释什么是“模型”,你通常会听到将它与“数据库”相关联的答案。据说模型就是数据库。该模型包含有关数据库的所有内容。但是,您很快就会发现,在简单的数据库访问类之上还有很多额外的逻辑。他需要我们进行数据验证、调用附加服务、发送电子邮件等等。什么是模型?该模型现在变得模棱两可,很难具体指代任何东西。根据开发中遇到的那么多词汇,我们可以理解他就是把应用程序划分成小而明确的类,有具体的职责。那么,这个困境的解决方案是什么?许多开发人员会在控制器之上添加更多逻辑。当控制器变大时,需要复用其他控制器中的一些逻辑层。许多人错误地认为_需要_调用当前控制器中的其他控制器,而不是将逻辑抽象到一个单独的类中。这种模式通常被称为“HMVC”。不幸的是,它的设计也很糟糕,而且通常控制器会很复杂。当您觉得需要在控制器中调用其他控制器时,HMVC(通常)预示着糟糕的设计?这说明现在的设计不好,controller里面的业务逻辑太负责任了。我们可以将逻辑抽象成一个公共类,以便在其他控制器中调用。总会有更好的编程。我们需要忘记留在脑海中的“模型”设计概念,所以让我们删除模型目录并重新开始。再见,模型你删除了你的模型目录了吗?如果没有,没关系,让他一个人呆着。让我们在应用程序下创建一个新文件夹,并将其简单命名为QuickBill。在后面的讨论中,我们之前给出的例子都会出现。注意使用场景请记住,如果你正在创建一个小型Laravel应用程序,在models下创建几个Eloquent模型还是合适的。然而,在本章中,我们将重点关注具有更多“分层”架构的复杂应用程序。我们已经有了与控制器和视图目录处于同一级别的app/QuickBill目录。我们可以在QuickBill下创建一些其他的目录,比如Repositories和Billing目录。创建目录后,记得在composer.json中注册PSR-0自动加载。"autoload":{"psr-0":{"QuickBill":"app/"}}现在,我们将Eloquent类放在QuickBill根目录下,我们可以方便地访问QuickBillUser、QuickBillPayment等。创建PaymentRepository和Repositories目录中的UserRepository类,并为数据访问方法getRecentPayments和getRichestUser编写代码。Billing目录包含用于使用第三方服务(例如“Stripe”和“Balanced”)的类和接口。上面的目录结构如下://app//QuickBill//Repositories->UserRepository.php->PaymentRepository.php//Billing->BillerInterface.php->StripeBiller.php//Notifications->BillingNotifierInterface.php->SmsBillingNotifier.phpUser.phpPayment.php数据校验放在哪里的问题通常让我们很头疼。可以考虑把它们放在“实体”类中,比如User.php或者Payment.php,方法名可以叫:validForCreation和hasValidDomain。或者您可以创建一个命名空间为Validation的UserValidator类,并将其注入到存储库类中。有两种方法,看个人喜好。通过摆脱模型目录,我们可以摆脱困境并实现良好的设计。当然,我们创建的很多项目都会有相似之处,再复杂的项目也会有数据访问(存储)层,以及其他服务层等等。不要害怕文件夹不要害怕创建更多文件夹,这是组织应用程序的好方法。通常我们想用它来将应用程序分成小的组件,每个组件都有自己特定的职责。不要被“模型”所限制。就像上面的例子一样,我们可以创建一个Repository来存储所有相关的类,以供数据访问。层次无处不在你应该已经注意到,一个好的应用程序设计应该有明确的职责划分和清晰的逻辑划分。该控件仅用于接收HTTP请求和请求逻辑处理类。业务处理层是整个应用的中心。它包含数据采集、数据验证、支付处理、电子邮件发送以及应用程序中的各种功能等库。事实上,业务逻辑不需要感知“网络”。网络只是连接到应用程序的传输机制,不应超出应用程序中的路由和控制器的范围。一个好的架构是经得起检验和研究的,是一个由清晰的代码组成的可持续发展的架构。例如,我们不是直接访问类中的网络请求实例,而是将网络请求输入传递??给控制器??。一个简单的改变就是将类从“网络”中分离出来。这样,测试时就不用担心重新模拟请求了:}publicfunctionpostCharge(){$this->biller->chargeAccount(Auth::user(),Input::get('amount'));返回View::make('charge.success');}}chargeAccount方法可以很方便地进行测试,只需要传入用于测试数据的整型数据,而不是使用包含Request和Input类的BillerInterface接口的实现类库将方法作为参数传入。职责分离是编写健壮应用程序的关键。关键是一个班管的是不是太多了。你应该经常问自己:“这个班级还关心X吗?”如果答案是“否”,则抽象逻辑并使用依赖注入来处理它。更改的原因很简单确定类库是否具有足够的职责分离的一种非常有用的方法是检查更改代码的原因。比如调整通知逻辑的时候,是不是也要修改Biller接口的实现?当然不是,Biller的实现只和支付有关,只需要按照约定和通知逻辑进行交互即可。牢记这种心态将帮助您快速改进应用程序的每个部分并使其健壮。“瓶瓶罐罐”放在哪里在使用Laravel开发应用的时候,经常会有这样的疑问,很多“东西”不知道放在哪里。例如,将“helper”函数放在哪里?活动筹备程序在哪里?视图组件应该放在哪里?答案可能会让您感到困惑:“任何地方”!Laravel没有文件所属位置的概念。然而,这个答案并不令人满意。在进一步讨论之前,让我们先讨论一下上述问题。辅助函数Laravel的辅助函数位于support/helpers.php文件中。或者,如果您也想创建自己的帮助文件,“start”目录是个好地方。请求应用时会引用start/global.php,我们可以在这里添加自己的helpers.php文件://Withinapp/start/global.phprequire_once__DIR__.'/../helpers.php';事件监听器当然,事件监听器不能属于routes.php文件,放在start文件中也不合适。我们必须选择另一个地方来放置它。服务提供商的目录很好。之前我们知道,服务提供者不仅仅是容器注册绑定的服务,还可以做很多其他的事情。它可以以清理代码且不影响应用程序逻辑的方式组织许多侦听器。视图组件也可以放在这个位置。它实际上类似于监听器,可以存储在服务提供者中。例如,用服务提供者组织监听器:计费事件...});创建提供程序后,只需将其添加到app/config/app.php配置中的提供程序数组即可。注意boot方法请记住,我们在上面的示例中使用boot的原因是,register方法只是用于将服务注册到容器中的方法。错误处理如果我们在应用程序中有自定义错误处理,请不要在“开始”文件中接管。另外,像事件监听器一样,最好组织在服务提供者中。Provider可以这样命名为QuickBillErrorProvider,并在boot方法中注册所有自定义错误处理。重申一下:我们希望将此代码与我们的逻辑分开。最终,自定义错误处理程序如下所示:e){//处理失败的计费异常...});}}简单的解决方法当然,在只有一两种错误处理方法的情况下,把他放在“开始”文件中也是一种简洁的方法。其他一般来说,类库应该在我们的应用程序中组织在PSR-0规范下。命令式代码,如事件监听、错误处理和其他“注册”类型的服务,最好在服务提供者中组织。根据以上原则,我们可以确定代码的组织规则。不要犹豫太多,Laravel就是为了方便我们业务的工作,这也是Laravel的宗旨。为您的应用程序找到合适的结构并与他人分享。如上,我们可以为所有自定义服务提供者添加一个命名空间Providers,并创建一个目录来组织它们://app//QuickBill//Billing//Extensions//Pagination->Environment.php//Providers->EventPusherServiceProvider。php//RepositoriesUser.phpPayment.php在上面的例子中,有两个命名空间,Extensions和Providers。定制的服务放在Providers目录下,扩展到框架的组件组织在与Extensions命名空间同名的目录下。