深入了解 Laravel 的依赖注入容器

发布于 作者

Learn all about Laravel's dependency injection container image

Laravel 拥有一个很棒的依赖注入容器,但很多人却避而远之。在本教程中,我将介绍如何利用 Laravels 容器让我的代码为我工作。

使用容器的关键在于组织 - 在一个一致的地方保存容器绑定,并使用有意义的命名约定,以便你能够了解正在发生的事情。毕竟,容器的有效性取决于放入其中的内容。

假设我们希望将所有绑定都放在一个地方,例如在服务提供者中。这听起来很合理吧?但当我们的应用程序不断发展时会发生什么?我们从一个简单的应用程序开始,可能只有 5-6 个绑定,然后添加了一些新功能,需要向容器添加更多绑定。不知不觉中,我们使用的服务提供者变得非常庞大,想要找到任何东西都需要花费大量的认知精力。

我们该如何解决这个问题?如何确保我们不是仅仅将绑定塞进服务提供者中来掩盖问题?让我带你了解我的方法。

我的主要 AppServiceProvider 是应用程序的入口点,因此我的工作是注册其关键区域。我依赖于领域驱动设计,因此每个领域都有一个服务提供者。我允许每个领域干净地管理其绑定。

final class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->register(
provider: AuthDomainServiceProvider::class,
);
 
$this->app->register(
provider: CommunicationDomainServiceProvider::class,
);
 
$this->app->register(
provider: WorkDomainServiceProvider::class,
);
}
}

使用这种方法,我可以根据需要启用和禁用领域,快速添加新领域,并从一个文件中概述应用程序中的所有领域。

当然,我会保留 Laravel 应用程序中的其他默认服务提供者,因为它们有自己的用途。现在让我们深入了解其中一个领域服务提供者,以理解它的用途。

final class AuthDomainServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->register(
provider: QueryServiceProvider::class,
);
 
$this->app->register(
provider: CommandServiceProvider::class,
);
 
$this->app->register(
provider: FactoryServiceProvider::class,
);
}
}

因此,我的身份验证服务提供者纯粹用于注册需要写入绑定的领域方面。

查询 - 这些是应用程序中的读取操作,是我需要执行的常见查询,或者是我需要执行的查询的一部分。我写了一篇关于我的方法的教程 这里.

命令 - 这些是应用程序中的写入操作。通常情况下,这些操作会被拉入后台作业,以便应用程序能够快速响应。

工厂 - 这些是数据对象工厂。我发现数据对象会变得很大很混乱,占用大量空间。我的解决方案是将它们移到专门的工厂中,以便我可以使用它们在应用程序中创建数据对象。

让我们看一下 CommandServiceProvider,以及我们如何在应用程序中有效地注册命令。

final class CommandServiceProvider extends ServiceProvider
{
public array $bindings = [
FindOrCreateUserContract::class => FindOrCreateUser::class,
GenerateApiTokenContract::class => GenerateApiToken::class,
SendPasswordResetContract::class => SendPasswordReset::class,
];
}

Laravel 允许你使用服务提供者上的 bindings 属性注册不需要传递参数的任何绑定。这可以使我们的服务提供者保持整洁。

让我们看一下这些绑定之一,以理解它们的外观和用途。

interface GenerateApiTokenContract
{
public function handle(Authenticatable $user, DataObjectContract $payload): Model|NewAccessToken;
}

然后我们继续进行实现。

final class GenerateApiToken implements GenerateApiTokenContract
{
public function handle(Authenticatable $user, DataObjectContract $payload): Model|NewAccessToken
{
return DB::transaction(
fn (): Model|NewAccessToken => $user->createToken(
name: $payload->name,
),
);
}
}

我们将写入操作包装在一个数据库事务中,然后使用注入的用户模型,并调用其上的 create token 方法,将 payload 中的 name 属性传递进去。这样可以保持代码整洁 - 因为你也可以使用它为应用程序中的任何用户生成 API 令牌,而不仅仅是当前登录的用户。

以这种方式使用容器意味着我的控制器始终保持干净和简洁。让我们看一下登录用户的 API 控制器示例。

final readonly class LoginController
{
public function __construct(
private GenerateApiTokenContract $command,
private TokenNameGenerator $generator,
) {}
 
public function __invoke(LoginRequest $request): Responsable
{
$request->authenticate();
 
return new TokenResponse(
data: TokenFactory::make(
data: $this->command->handle(
user: auth()->user(),
payload: new TokenRequest(
name: $generator->generate(),
),
),
),
);
}
}

当然,你可以随意拆分这段代码,例如为它提供更多空间。但对我来说,这就是我的目标。我依赖于容器,并利用 Laravel 的优势,通过将小的移动部件组合起来,实现最终目标。

Steve McDougall photo

技术作家,就职于 Laravel 新闻,开发者倡导者,就职于 Treblle。API 专家,经验丰富的 PHP/Laravel 工程师。 YouTube 直播主.

Cube

Laravel 新闻简报

加入 40,000 多名其他开发者,不错过任何新提示、教程等。

Laravel Forge logo

Laravel Forge

轻松创建和管理你的服务器,并在几秒钟内部署你的 Laravel 应用程序。

Laravel Forge
Tinkerwell logo

Tinkerwell

Laravel 开发人员必备的代码运行器。使用 AI、自动完成和本地和生产环境中的即时反馈进行调试。

Tinkerwell
No Compromises logo

不妥协

Joel 和 Aaron,两位来自不妥协播客的经验丰富的开发者,现在可以为你的 Laravel 项目提供服务。 ⬧ 每月 7500 美元的固定费用。 ⬧ 没有漫长的销售流程。 ⬧ 没有合同。 ⬧ 100% 满意退款保证。

不妥协
Kirschbaum logo

Kirschbaum

提供创新和稳定性,确保你的 Web 应用程序取得成功。

Kirschbaum
Shift logo

Shift

运行旧版本的 Laravel?即时、自动化的 Laravel 升级和代码现代化,让你的应用程序保持新鲜。

Shift
Bacancy logo

Bacancy

仅需每月 2500 美元,即可为你的项目配备经验丰富的 Laravel 开发人员(具有 4-6 年的经验)。获得 160 小时的专业知识和 15 天的免费试用期。立即安排通话!

Bacancy
Lucky Media logo

Lucky Media

立即获得幸运 - Laravel 开发的理想选择,拥有十多年的经验!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel 电子商务

Laravel 的电子商务。一个开源包,将现代无头电子商务功能的强大功能引入 Laravel。

Lunar: Laravel 电子商务
LaraJobs logo

LaraJobs

官方 Laravel 工作板

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS 启动工具包

SaaSykit 是一个 Laravel SaaS 启动工具包,包含运行现代 SaaS 所需的所有功能。支付、漂亮的结账、管理面板、用户仪表板、身份验证、现成组件、统计信息、博客、文档等等。

SaaSykit: Laravel SaaS 启动工具包
Rector logo

Rector

你的合作伙伴,助你顺利升级 Laravel,降低成本,加速创新,打造成功的企业

Rector
MongoDB logo

MongoDB

通过 MongoDB 和 Laravel 的强大集成,增强你的 PHP 应用程序,使开发人员能够轻松高效地构建应用程序。支持事务、搜索、分析和移动用例,同时使用熟悉的 Eloquent API。探索灵活、现代的 MongoDB 数据库如何改变你的 Laravel 应用程序。

MongoDB
Maska is a Simple Zero-dependency Input Mask Library image

Maska 是一个简单的零依赖输入掩码库

阅读文章
Add Swagger UI to Your Laravel Application image

在你的 Laravel 应用程序中添加 Swagger UI

阅读文章
Assert the Exact JSON Structure of a Response in Laravel 11.19 image

在 Laravel 11.19 中断言响应的 JSON 结构

阅读文章
Build SSH Apps with PHP and Laravel Prompts image

使用 PHP 和 Laravel Prompts 构建 SSH 应用程序

阅读文章
Building fast, fuzzy site search with Laravel and Typesense image

使用 Laravel 和 Typesense 构建快速、模糊的网站搜索

阅读文章
Add Comments to your Laravel Application with the Commenter Package image

使用 Commenter 包向你的 Laravel 应用程序添加评论

阅读文章