laravel 6 中应使用 singleton() 绑定业务类以确保单例复用,避免用 bind() 导致重复创建;需在 register() 中绑定,禁用 boot();instance() 仅适用于已完全初始化的对象。

在 Laravel 6 中,服务容器本身不是用来“保存全局业务实例”的仓库,而是按需生成和管理对象的工厂。所谓“保存全局业务实例”,实际是指让某个业务类在整个请求生命周期(或更长)内复用同一个实例——这必须通过 singleton() 绑定实现,而不是靠手动存取变量或滥用 bind()。
用 singleton() 绑定业务类,确保单例复用
业务类(如订单处理器、支付网关客户端、用户上下文管理器)通常持有状态或外部连接,必须全局唯一。在 AppServiceProvider@register() 中绑定:
$this->app->singleton(OrderProcessor::class, function ($app) { return new OrderProcessor($app->make('cache')); });- 接口绑定也支持单例:
$this->app->singleton(PaymentGateway::class, AlipayGateway::class); - 避免在
boot()中注册 singleton —— 此时容器已开始解析依赖,绑定可能被跳过,尤其在队列或 Artisan 命令中失效
验证是否真正复用同一实例
写个简单测试确认它没被重复创建:
$a = app()->make(OrderProcessor::class);$b = app()->make(OrderProcessor::class);var_dump($a === $b); // 必须输出 true- 若为 false,说明误用了
bind()或绑定时机错误
慎用 instance():只用于已完全初始化的对象
如果你已在某处(如中间件或启动逻辑)手动构建好业务实例,且确保所有依赖(配置、连接、环境变量)均已就绪,才可用 instance() 注入:
$context = new UserContext(request()->user());$this->app->instance(UserContext::class, $context);- 切勿传入未初始化的实例,例如
new SmsService()却还没加载config('services.twilio'),否则后续调用直接报错
不要用 bind() 保存“全局业务实例”
bind() 每次调用都新建对象,看似方便,但对业务类是危险操作:
- 订单处理器若用
bind(),每次 make 都新建,事务状态、缓存引用、连接句柄全丢失 - 数据库连接类用
bind()→ 每次请求新建连接 → 连接池迅速耗尽 - 只有无状态类(如 DTO、策略类、表单请求类)才适合
bind()











