服务容器
简介
Laravel 服务容器是一个用于管理类依赖以及实现依赖注入的强有力工具。依赖注入这个名词表面看起来花哨,实质上是指:通过构造函数,或者某些情况下通过「setter」方法将类依赖「注入」到类中。
我们来看一个简单的例子:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Repositories\UserRepository;
use App\Models\User;
use Illuminate\View\View;
class UserController extends Controller
{
/**
* 创建一个新的控制器实例
*/
public function __construct(
protected UserRepository $users,
) {}
/**
* 展示给定用户的信息
*/
public function show(string $id): View
{
$user = $this->users->find($id);
return view('user.profile', ['user' => $user]);
}
}
在此示例中,UserController
需要从数据源中检索用户。 因此,我们将 注入 一个能够检索用户的服务。 在这种情况下,我们的 UserRepository
很可能使用 Eloquent 从数据库中检索用户信息。 然而,由于存储库是注入的,我们可以很容易地用另一个实现替换它。 这种方式的便利之处也体现在:当需要为应用编写测试的时候,我们也可以很轻松地 「模拟」 或者创建一个 UserRepository
的伪实现来操作。
深入理解服务容器,对于构建一个强大的、大型的应用,以及对 Laravel 核心本身的贡献都是至关重要的。
零配置解决方案
如果一个类没有依赖项或只依赖于其他具体类(而不是接口),则不需要指定容器如何解析该类。例如,你可以将以下代码放在 routes/web.php
文件中:
<?php
class Service
{
// ...
}
Route::get('/', function (Service $service) {
die(get_class($service));
});
在这个例子中,点击应用程序的 /
路由将自动解析 Service
类并将其注入到路由的处理程序中。 这是一个有趣的改变。 这意味着你可以开发应用程序并利用依赖注入,而不必担心臃肿的配置文件。
很荣幸的通知你,在构建 Laravel 应用程序时,你将要编写的许多类都可以通过容器自动接收它们的依赖关系,包括 控制器、 事件监听器、 中间件 等等。 此外,你可以在 队列系统 的 handle
方法中键入提示依赖项。 一旦你尝到了自动和零配置依赖注入的力量,你就会觉得没有它是不可以开发的。
何时使用容器
得益于零配置解决方案,通常情况下,你只需要在路由、控制器、事件侦听器和其他地方键入提示依赖项,而不必手动与容器打交道。例如,可以在路由定义中键入 Illuminate\Http\Request
对象,以便轻松访问当前请求的 Request 类。尽管我们不必与容器交互来编写此代码,但它在幕后管理着这些依赖项的注入:
use Illuminate\Http\Request;
Route::get('/', function (Request $request) {
// ...
});
在许多情况下,由于自动依赖注入和 facades ,你在构建 Laravel 应用程序,而无需手动绑定或解析容器中的任何内容。 那么,你什么时候会手动与容器打交道呢? 让我们来看看下面两种情况。
首先,如果你编写了一个实现接口的类,并希望在路由或类的构造函数上键入该接口的提示,则必须 告诉容器如何解析该接口。第二,如果你正在 编写一个 Laravel 包 计划与其他 Laravel 开发人员共享,那么你可能需要将包的服务绑定到容器中。