目录

容器和依赖注入大部分人官方文档难以消化,一方面两个概念不好理解,过于术语化,问文档范例没有更接地气的范例。

首先我们要弄明白依赖注入是什么,为什么需要依赖注入,可以看看:03-依赖倒置原则

如果还不懂得依赖注入的概念:

IOC/DI通俗解释

控制反转与依赖注入的理解

容器

ThinkPHP引入的容器,到底是什么意思?

官方是这么说的:ThinkPHP使用容器来更方便的管理类依赖及运行依赖注入。容器和依赖注入 · ThinkPHP6.0完全开发手册 · 看云

通俗点说就是:tp6实现了个容器类,这个类专门处理依赖注入的实例对象,比如框架内置绑定到容器中的类有:

内置类库 容器绑定标识
think\Cache cache
think\Config config
think\Cookie cookie
think\Request request
think\Response response
think\Filesystem filesystem
think\Route route
think\Session session
- -

当然我们也可以将自定义类注入到容器中,供业务逻辑类使用,举个例子:

class A(){

    private $b;
    public function __construct(Request $request, B $b){
        $this->b = $b;
    }
}

class B(){
    //...
}

//没有使用依赖注入之前,我们需要手动实例化B对象,并传参给类A,进行实例化:
$a = new A(new think\Request(), new B());
//如果使用tp6的依赖注入,通过助手函数invoke:
$a = invoke('A');//框架会通过依赖注入,将实例化B,并注册到框架容器中,省去了手动实例化,及可以在容器类中统一管理这些注入对象

依赖注入的类统一由容器进行管理,大多数情况下是在自动绑定并且实例化的。

绑定与解析类库

除了调用时自动注入容器外,我们还可以手动绑定类库到容器中。

可以对已有的类库绑定一个标识(唯一),便于快速调用。

// 绑定类库标识
$this->app->bind('think\Cache', 'app\common\Cache');

// 或者使用助手函数 绑定类库标识
bind('cache', 'think\Cache');

//绑定一个闭包
bind('sayHello', function ($name) {
    return 'hello,' . $name;
});

// 绑定类实例
$cache = new think\Cache;
bind('cache', $cache);

//使用助手函数app解析使用容器中的类或对象或函数等
$cache = app('cache');

批量绑定

在实际应用开发过程,不需要手动绑定,我们只需要在app目录下面定义provider.php文件(只能在全局定义,不支持应用单独定义),系统会自动批量绑定类库到容器中。

return [
    'route'      => \think\Route::class,
    'session'    => \think\Session::class,
    'url'        => \think\Url::class,
];

注意:绑定标识主要是为了方便记住与快速使用,我们也可以解析一个未绑定的类,只是没有简短的标识,需要类完整命名空间路径:

$arrayItem = app('org\utils\ArrayItem');

依赖注入场景

了解了依赖注入后,再去看TP官方关于依赖注入的使用

依赖注入的对象参数支持多个,且与顺序无关

以下场景支持依赖注入:

  • 控制器构造方法
  • 控制器操作方法
  • 路由的闭包定义
  • 事件类的执行方法
  • 中间件的执行方法等