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

大型Laravel应用

时间:2023-03-30 01:46:34 PHP

文章转发自专业的Laravel开发者社区,原文链接:https://learnku.com/laravel/t...(如果只想看解决方案,点这里)Laravel是迄今为止最流行的PHP框架,目录结构清晰,语法优雅。使用Laravel提供的默认目录结构非常适合中小型项目,但是当您拥有超过50个模型的大型应用程序时,代码库可能会有点令人窒息。维护一个大型应用程序并不容易,尤其是当它杂乱无章时,Laravel的默认结构在这种情况下肯定帮不上什么忙。首先,我们来看看Laravel默认结构以及它如何影响大型应用程序。Laravel默认的应用结构:|-app/|-Console/|-Commands/|-Events/|-Exceptions/|-Http/|-Controllers/|-Middleware/|-Jobs/|-Listeners/|-Providers/|-User.php|-database/|-factories/|-migrations/|-seeders/|-config/|-routes/|-resources/|-assets/|-lang/|-views/结构很好。但是,当我们在大型应用程序中工作时,我们通常会将业务逻辑划分为存储库、转换器等...像这样:|-app/|-Console/|-Commands/|-Events/|-Exceptions/|-Http/|-Controllers/|-Middleware/|-Jobs/|-Listeners/|-Models/|-Presenters/|-Providers/|-Repositories/|-Services/|-Transformers/|-Validators/|-database/|-factories/|-migrations/|-seeders|-config/|-routes/|-resources/|-assets/|-lang/|-views/这显然是一个结构良好的Laravel项目。现在,让我们看一下模型文件夹:|-app/|-Models/|-User.php|-Role.php|-Permission.php|-Merchant.php|-Store.php|-Product.php|-Category.php|-Tag.php|-Client.php|-Delivery.php|-Invoice.php|-Wallet.php|-Payment.php|-Report.php我们还需要处理所有业务逻辑服务。还有包含相同或更多类的Repositories、Transformers、Validators文件夹。但是,使用单个实体/模型需要浏览不同的文件夹和文件。问题不在于浏览不同的文件夹,而是维护代码和服务之间的通信。分析代码库,我们发现:是一个整体的应用,开发者维护困难,开发效率低(需要时刻考虑相互连接),Scaling有问题,解决方案很明显——微服务。即使我们使用soa(面向服务的架构),我们仍然必须将我们的整体应用程序分解为更小的独立部分以分别扩展它们。通常解耦服务需要两个简单的步骤:将服务的子例程(模型、存储库、转换器等)移动到一个新的更小的php微服务应用程序中。重置服务函数调用以将目标重定向到微服务(例如:创建一个http请求)。现在您需要找到与该服务相关的所有文件,您可能会发现通过绕过该服务,它在代码的其他地方使用了它的模型或存储库。总结一下你可能会遇到的问题:考虑的文件太多出错几率大导致烦躁有时需要重新思考领域逻辑新程序员祭天最后一个原因很重要,因为新开发人员很难掌握一个整个应用程序的时间很短。但是,项目经理不会给他太多时间。这会导致草率的修补、错误的代码放置,甚至给下一个新开发人员带来更多的困惑。幸运的是,我们已经有了解决方案——HMVC。将整个应用程序分成更小的部分,每个部分都有自己的文件和文件夹(例如app/文件夹),但是HMVC增加了更多的复杂性,当我们想将特定模块移动到微服务中时也是如此。我们仍然需要在主代码库中保留控制器、中间件等。在大多数情况下,迁移到微服务需要重新定义路由和控制器。因此,我们不得不做多余的工作。因此,我不太喜欢这种结构。因为,我只想分开我(必须)不必分开的东西。并通过composer.json自动加载加载,如下:|-auth/|-Exceptions/|-Http/|-Listeners/|-Models/|-Presenters/|-Providers/|-Repositories/|-Services/|-Transformers/|-Validators/|-merchant/|-Console/|-Events/|-Exceptions/|-Http/|-Jobs/|-Listeners/|-Models/|-Presenters/|-Providers/|-Repositories/|-Services/|-Transformers/|-Validators/|-database/|-factories/|-migrations/|-seeders|-config/|-routes/|-resources/|-assets/|-lang/|-views/但HMVC增加了更多的复杂性,并且当我们想要将特定模块移动到微服务中时。我们仍然需要在主代码库中保留控制器、中间件等。在大多数情况下,转向微服务需要重新定义路由和控制器,我们不得不做一些冗余的工作。但是,我只想分离我(必须)必须分离的东西。领域驱动设计本文将不再过多介绍领域驱动设计。DeveloperulDeLaUnu在此处对DDD进行了很好的描述。从本文的角度来看,DDD(可以)将一个Laravel应用程序分为4个部分(或3个......见):应用程序-通常包含,控制器,中间件,路由域-通常包含业务逻辑(模型,存储库,transformers,policies,etc.)Infrastructure-通常有公共服务,例如日志记录、电子邮件等interface-通常包含视图、语言、资产如果我们以这种方式构建应用程序并使用命名空间,结果会是什么?|-app/|-Http/(应用程序)|-Controllers/|-Middleware/|-Domain/|-Models/|-Repositories/|-Presenters/|-Transformers/|-Validators/|-Services/|-Infrastructure/|-控制台/|-异常/|-提供者/|-事件/|-工作/|-监听器/|-资源/(接口)|-资产/|-语言/|-视图/|-路由/|-api.php|-web.php像这样将项目分成文件夹是行不通的,这意味着我们只是添加了一个父命名空间。解决方案如下:|-app/|-Http/|-Controllers/|-Middleware/|-Providers/|-Account/|-Console/|-Exceptions/|-Events/|-Jobs/|-Listeners/|-Models/|-User.php|-Role.php|-Permission.php|-Repositories/|-Presenters/|-Transformers/|-Validators/|-Auth.php|-Acl.php|-Merchant/|-Payment/|-Invoice/|-resources/|-routes/Auth.php和Acl.php是app/Account/文件夹中的服务文件。控制器只会访问这两个类并调用它们的函数。其他类(域外)将无法访问app/Account/文件夹中的其余类。这些服务中的函数将只接受基本的PHP数据类型,例如数组、字符串、整数、布尔和POPO(普通旧PHP对象),但不接受类的实例。例如:publicfunctionregister(array$attr){...}publicfunctionlogin(array$credentials){...}publicfunctionlogout(){...}注意register函数接收的是数组属性,而不是用户对象。因为调用该函数的另一个类不应该知道User模型的存在。这是整个结构的基本规律。当我们想要分离代码时,我们的应用程序开始变大,然后我们想要将Account域分离到一个微服务中,并将其变成一个OAuth服务。因此,我们只需移动以下部分-|-Account/|-Console/|-Exceptions/|-Events/|-Jobs/|-Listeners/|-Models/|-User.php|-Role.php|-Permission.php|-Repositories/|-Presenters/|-Transformers/|-Validators/|-Auth.php|-Acl.php到新的Laravel(或Lumen)应用程序-|-app/|-Http/|-Controllers/|-中间件/|-账户/|-事件/|-Jobs/|-Listeners/|-Models/|-User.php|-Role.php|-Permission.php|-Repositories/|-Presenters/|-Transformers/|-Validators/|-Auth.php|-Acl.php|-routes/|-resources/当然我们还要在controller和routes里面写代码,让它成为我们需要的OAuth服务。但是我们需要在主代码库中更改什么?我们只需要保留Auth.php和Acl.php的服务文件,将其函数中的代码更改为对新建微服务的HTTP请求(或其他消息传递方式)即可。...publicfunctionlogin(array$credentials){//更改此处的代码}...整个应用程序将保持不变。应用程序结构将如下所示-|-app/|-Console/|-Exceptions/|-Http/|-Controllers/|-Middleware/|-Providers/|-Account/|-Auth.php|-Acl.php|-Merchant/|-Payment/|-Invoice/|-resources/|-routes/via通过这种更少的努力,您可以将部分代码移动到一个完全独立的微服务中。我无法想象任何其他方法可以将部分代码移动到另一个操作更少的微服务。权衡正如我之前所说,任何事情都需要权衡,这个解决方案也不例外。这里我们有一个关于迁移的问题!因为在上面的文件结构中(分离前),所有的迁移文件都放在database/migrations/目录下。但是当我们想要分离一个域时,我们还需要识别这些文件并移动到一个新的域名。这可能很困难,因为我们没有任何明确指示哪个迁移文件属于哪个域名。我们需要知道如何在迁移文件中放置标识符。这个标识符可以是域名前缀例如,我们可以将迁移文件命名为xxxxxxxxx_create_account_users_table.php而不是xxxxxxxxx_create_users_table.php。如果需要,我们也可以使用account_users表名而不是用户。我更喜欢确定哪些表需要拆分移动。令人沮丧,但如果我们使用前缀或其他类型的标记,这个过程就会不那么痛苦。我仍在试验这种迁移结构,并计划构建一个Laravel包,它将提供artisan命令来自动生成文件。完成后我会把包的链接放在这里。