Laravel 6 接口绑定必须在服务提供者的 register() 方法中完成,使用 bind() 或 singleton() 显式指定实例化策略,控制器和视图可通过类型提示自动解析,验证可用 app()->make() 测试。

Laravel 6 的服务容器支持接口绑定,核心是把接口(contract)映射到具体实现类,让依赖注入时自动用实现类来填充类型提示。关键不在“能不能”,而在“怎么绑才生效、不踩坑”。
接口绑定必须在 register() 中完成
所有接口绑定操作,必须写在服务提供者(如 AppServiceProvider)的 register() 方法里。boot() 阶段再绑定就晚了——容器已经开始解析依赖,尤其在队列任务、Artisan 命令或测试中,绑定极可能被跳过,导致 Target class [xxx] does not exist 或解析出错。
- 正确位置:
app/Providers/AppServiceProvider.php → register() - 错误写法:在
boot()里调用$this->app->bind(...) - 绑定示例:
$this->app->bind(EmailSender::class, MailgunSender::class);
选对绑定方式:bind() vs singleton()
接口绑定后,实例化策略决定运行时行为。Laravel 6 不会自动判断该用单例还是普通实例,必须显式指定。
- 用 bind():每次请求都新建对象,适合无状态轻量类(如格式化器、策略类)
- 用 singleton():首次创建后全程复用,适用于有状态或高开销服务(如数据库连接、缓存客户端、HTTP 客户端)
- 错误示例:用
bind()绑定 Redis 客户端 → 每次请求新建连接,很快耗尽连接池 - 正确写法:
$this->app->singleton(CacheContract::class, RedisCache::class);
控制器和视图中使用接口注入
绑定完成后,Laravel 6 会自动通过类型提示解析接口,无需手动 app()->make()。
- 控制器构造函数注入:
public function __construct(EmailSender $sender) { ... } - Blade 视图中注入:
@inject('mailer', 'App\Contracts\EmailSender'),然后直接用{{ $mailer->send(...) }} - 注意:视图注入的类名必须与绑定时的接口全限定名完全一致
验证绑定是否生效
最简单的方式是临时在路由闭包或 Tinker 中测试:
-
app()->make(App\Contracts\EmailSender::class)能返回实例,说明绑定成功 - 如果是 singleton,两次调用结果应为同一对象:
app()->make(X::class) === app()->make(X::class)返回 true - 若报错 “Class xxx does not exist”,检查命名空间是否拼错、类文件是否存在、是否已执行
composer dump-autoload


















