关于 Laravel 容器的使用,大家都是什么情况下用?

我还没有很好的理解laravel容器。
我的理解是,容器里放了好多的可供调用的对象。
需要时可以直接使用,无需new等。

想问一下,大家都会用到这个特性么?
项目中一般怎么去用这个特性呢?是分出个service层,然后把各个service都放到容器里?
在controller里调用?
还是直接不用呢?

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 3

我觉得不要纠结如何去使用,相反容器提供的是一种创建实例的方法,根据不同情况可以灵活选择。

  1. 首先就是方法注入了。不管在构造方法中还是在普通方法中,通过对变量使用类的类型提示,容器会自动创建一个实例并赋给这个变量,比如一个 Work 类的构造函数:
    public function __construct(Service $service)
    {
        $this->service = $service ;
    }

    这种方式使用的局限性就是这个 Work 消费类不可以使用 new 关键字创建实例,不能用new Work(),必须使用容器的依赖注入。

  2. 使用容器的make方法,这个就是解决上面这个问题的。有的时候我们使用外部包,这个包对 Work 有个依赖,他需要一个Work 的实例,但是work包对Service 又有依赖,你也不能随便把包改成依赖注入,这个时候可以改造 Work 类:
    public function __construct()
    {
        $this->service = app(Service::class);
    }

    这个时候就可以通过new 创建一个 Work 的实例并传入到包中。

  3. 第三个就是通过服务提供者注册一些特别的绑定;一般来说如果你的类不需要通过接口或者 alias 来注入的话,就没必要在服务提供者里面注册,因为容器解析实例的过程是先查找容器中的实例和服务提供者里面的绑定,如果查找不到就会自动使用new 关键字创建。

容器里面存储的实际上是一些key=>value的数组。其中key就是我们在方法注入的类型提示或者make()方法中的参数,实际上就是一个字符串。value代表的是实际上实例化的类。

服务提供者有什么作用呢?

如果你的key和value 是同一个的话,像 app(Work::class) 你想获得的就是 Work 的实例,传入的也是 Work 的类名,这个时候不用在服务提供者里面注册。

假如你 app(Work::class) 你想获得的是一个 WorkHard 的实例,这种情况下就需要在服务提供者里面注册,也就是告诉容器,当我访问Work::class这个key的时候,请给我一个 WorkHard 的实例。

服务容器绑定又有几个不同的方法,比如 bind() , singleton(), instance() 等,通常绑定一个接口到一个特定的类,会使用bind方法,如果需要获得一个单例的话,就用singleton()方法,singleton()会在注入的时候查找是否已经存在实例,存在的话直接返回而不是创建一个新的实例。instance()是绑定到一个已经存在的实例,我用的比较少。

当然一次性加载所有的服务提供者需要创建所有的实例,相对来说耗费资源吧,也可以在服务提供者里面设置为延迟加载,当真的使用到这个注入的时候才会创建。

一点小心得,欢迎指正。

7年前 评论

@lx1036 感谢细致回答。
我的意思是项目中自己使用更多的使用。
比如是否需要分service层
然后用这种方式去调用

7年前 评论

我觉得不要纠结如何去使用,相反容器提供的是一种创建实例的方法,根据不同情况可以灵活选择。

  1. 首先就是方法注入了。不管在构造方法中还是在普通方法中,通过对变量使用类的类型提示,容器会自动创建一个实例并赋给这个变量,比如一个 Work 类的构造函数:
    public function __construct(Service $service)
    {
        $this->service = $service ;
    }

    这种方式使用的局限性就是这个 Work 消费类不可以使用 new 关键字创建实例,不能用new Work(),必须使用容器的依赖注入。

  2. 使用容器的make方法,这个就是解决上面这个问题的。有的时候我们使用外部包,这个包对 Work 有个依赖,他需要一个Work 的实例,但是work包对Service 又有依赖,你也不能随便把包改成依赖注入,这个时候可以改造 Work 类:
    public function __construct()
    {
        $this->service = app(Service::class);
    }

    这个时候就可以通过new 创建一个 Work 的实例并传入到包中。

  3. 第三个就是通过服务提供者注册一些特别的绑定;一般来说如果你的类不需要通过接口或者 alias 来注入的话,就没必要在服务提供者里面注册,因为容器解析实例的过程是先查找容器中的实例和服务提供者里面的绑定,如果查找不到就会自动使用new 关键字创建。

容器里面存储的实际上是一些key=>value的数组。其中key就是我们在方法注入的类型提示或者make()方法中的参数,实际上就是一个字符串。value代表的是实际上实例化的类。

服务提供者有什么作用呢?

如果你的key和value 是同一个的话,像 app(Work::class) 你想获得的就是 Work 的实例,传入的也是 Work 的类名,这个时候不用在服务提供者里面注册。

假如你 app(Work::class) 你想获得的是一个 WorkHard 的实例,这种情况下就需要在服务提供者里面注册,也就是告诉容器,当我访问Work::class这个key的时候,请给我一个 WorkHard 的实例。

服务容器绑定又有几个不同的方法,比如 bind() , singleton(), instance() 等,通常绑定一个接口到一个特定的类,会使用bind方法,如果需要获得一个单例的话,就用singleton()方法,singleton()会在注入的时候查找是否已经存在实例,存在的话直接返回而不是创建一个新的实例。instance()是绑定到一个已经存在的实例,我用的比较少。

当然一次性加载所有的服务提供者需要创建所有的实例,相对来说耗费资源吧,也可以在服务提供者里面设置为延迟加载,当真的使用到这个注入的时候才会创建。

一点小心得,欢迎指正。

7年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!