Laravel 5.4 如何向 IoC 容器中添加自己定义的类

原文地址:
http://www.cf2z.club/blog/how-does-laravel...

  1. 假设我们要建一个交易类,app/Trade/Sale.php
    <?php
    namespace App\Trade;
    class Sale
    {
    public function exchange()
    {
        dd('交易成功啦!');
    }
    }
  2. 在Providers目录下创建一个服务提供者 TradeServiceProvider
    php artisan make:provider TradeServiceProvider
  3. 然后在 TradeServiceProvider.php 的register方法中将我们的类进行绑定
    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        //
        $this->app->bind('trade',function(){
            return new Sale();
        });
    }
  4. 接下来要去 config/app.php 下的providers数组中增加一行,
    App\Providers\TradeServiceProvider::class,
  5. 然后在我们的路由中写一个测试
    Route::get('/',function (){
    $trade = app('trade');
    dd($trade->exchange());
    }
    输出结果:交易成功啦!
  6. 至此我们就将我们自己的类添加到IoC 容器中了
本作品采用《CC 协议》,转载必须注明作者和本文链接
zf
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 13
$this->app->bind('trade',function(){
        return new Sale();//这里不需要命名空间 ?  return new App\Trade\Sale();
    });
6年前 评论

我在这个类的上面use 了,
这是我这个类的完整代码:

<?php
namespace App\Providers;
use App\Trade\Sale;
use Illuminate\Support\ServiceProvider;
class TradeServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
    }
    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind('trade',function(){
            return new Sale();
        });
    }
}
6年前 评论

$trade = app(App\Providers\TradeServiceProvider::class);

这样也可以

6年前 评论

我试了一下,@YuxiangDong 这样写好像不可以,
不过可以用另一种依赖注入的写法可以试一下能成功:

Route::get('/',function (\App\Trade\Sale $trade){
 dd($trade->exchange());
}
6年前 评论

自定义的类,不是基于接口而且构造函数没有带参数的情况下可以不用绑定到容器,在解析的时候会自动反射出来的

6年前 评论

这种是定义服务,如果是自己的类的话,直接 App::make('App\Trade\Sale') 或者 use App\Trade\Sale;App::make(Sale::class)就可以了

6年前 评论

@leoyang 对也不对,假如类的构造函数带参数,直接make会抛出无法解析参数的异常

6年前 评论

@翁航 错了,make函数自带解析构造函数参数的功能,要不然你以为 laravel 的依赖注入是怎么实现的?如果你的构造函数里面有你想手动赋值的值,还可以使用 resolve 函数传入参数,如果有问题可以看一下我的博客:博客:Laravel 核心——IoC 服务容器源码解析(服务器解析)

6年前 评论

@leoyang
假如没有放到容器中的话,直接 App::make('App\Trade\Sale') 或者 use App\Trade\Sale;App::make(Sale::class)的类构造函数必须没有参数,如果有参数必须在make的时候传递进去否则会抛出异常。当然不绝对,假如参数有类型提示,而且提示的类也在容器或者满足上述条件,则没问题

6年前 评论

@翁航 如果构造函数参数连类型提示都没有的话,楼主这种容器绑定方法也搞不定吧。再有如果类构造函数没有参数,那为什么要用容器,直接 new 不是更好吗?类构造函数参数的类型提示这种在 laravel 一般都是必须的,否则根本没办法通过反射进行依赖注入,写出来的自定义类也就只能自己才会用了

6年前 评论

@leoyang 是这样没错,如果一个类构造函数没有参数,完全可以直接new,没有必要放到容器中。但是假如要基于一个接口的话,那就有必要了。文档中有这样的一句话:

注:如果一个类没有基于任何接口那么就没有必要将其绑定到容器。容器并不需要被告知如何构建对象,因为它会使用 PHP 的反射服务自动解析出具体的对象。

虽然会自动反射解析出具体的对象,但是假如一个类长这样:(当然还有一种基于上下文绑定的情况,这里不深究。)

class Summary{
    public function __construct($foo, $bar){

    }
}

那就必须先放到容器,才可以解析。否则直接make绝对抛异常。如果类长这样,那就可以不用放入也可以解析,前提FooBar类也满足以上的规则:

class Summary{
    public function __construct(Foo $foo, Bar $bar){

    }
}

其实我想要表达,一个类没有参数就没必要放入容器,可以直接new或者App::make(),这两种是完全一样的。假如有参数,一般都建议放到容器中再。

6年前 评论

@翁航 有道理,但是像我之前说的,你说的这种情况可以借助 APP::resolve 函数手动传入参数,也完全没有必要使用服务事先去绑定,因为服务是默认启动的,会造成框架的臃肿。

再说你的这个例子来绑定也是手动传参数给 bind 函数,服务容器再强大,你不传这种参数,它解析时也是要调用 make 函数,也是要报错的,并不是只要绑定容器就高枕无忧了,就不需要强制类型了。想要用依赖注入,就要在函数参数上强制类型,或者绑定时/解析时手动传参,否则就是要抛异常。

6年前 评论
qiuyuhome

果然评论才是最精彩的.

5年前 评论

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