laravel 6模型事件不支持自动依赖注入,需通过app()->make()手动解析依赖或使用监听器类实现构造函数注入,前提是服务容器已初始化且接口已正确绑定。

Laravel 6 的模型事件(如 creating、saving、updated 等)默认运行在模型静态上下文中,不经过服务容器自动解析,因此不能直接在事件闭包或监听器中使用构造函数依赖注入。但你可以通过服务容器手动获取依赖实例,前提是确保容器已可用且绑定已注册。
确保服务容器可访问
模型事件回调(尤其是用闭包定义的)执行时,Laravel 的应用实例(即服务容器)可能尚未完全初始化,或不在请求生命周期内(例如在 Artisan 命令、队列任务或 Tinker 中触发)。所以第一步是确认 app() 可用:
- 在 HTTP 请求生命周期中(如控制器调用
save()),app()通常可用; - 在队列任务或命令中,需确保应用已启动(Laravel 6 默认支持);
- 避免在模型静态属性或未初始化的上下文中调用
app(),否则会报错Call to a member function make() on null。
在模型事件闭包中手动解析依赖
推荐在 boot() 方法中注册事件,并用 app()->make() 获取所需服务:
class User extends Model
{
protected static function boot()
{
parent::boot();
static::created(function ($user) {
// ✅ 安全:app() 在请求周期中可用
$logger = app()->make(\Psr\Log\LoggerInterface::class);
$notifier = app()->make(\App\Services\NotificationService::class);
$logger->info('User created', ['id' => $user->id]);
$notifier->sendWelcomeEmail($user);
});
}
}
注意:不要在闭包中使用类型提示(如 function (User $user, NotificationService $notifier)),这不会被自动解析。
使用事件监听器类(更规范、支持完整 DI)
将逻辑抽离到独立监听器类中,该类本身由容器管理,可正常使用构造函数注入:
- 生成监听器:
php artisan make:listener SendWelcomeEmailOnUserCreated --event=UserCreated; - 在监听器构造函数中声明依赖,Laravel 自动注入;
- 在
EventServiceProvider中注册事件与监听器映射; - 在模型中分发事件(需先触发事件,而非直接用静态事件)。
示例:
// 在 User 模型中
protected static function boot()
{
parent::boot();
static::created(function ($user) {
event(new UserCreated($user)); // 分发自定义事件
});
}
// 监听器类(支持完整依赖注入)
class SendWelcomeEmailOnUserCreated
{
private $notificationService;
private $logger;
public function __construct(
\App\Services\NotificationService $notificationService,
\Psr\Log\LoggerInterface $logger
) {
$this->notificationService = $notificationService;
$this->logger = $logger;
}
public function handle(UserCreated $event)
{
$this->logger->info('Handling user creation...');
$this->notificationService->sendWelcomeEmail($event->user);
}
}
绑定接口实现(关键前提)
若依赖的是接口(如 UserRepository),必须提前在 AppServiceProvider@register() 中绑定:
$this->app->bind(
\App\Repositories\UserRepository::class,
\App\Repositories\EloquentUserRepository::class
);
否则 app()->make(UserRepository::class) 会抛出 Target [..] is not instantiable 错误。
不复杂但容易忽略:模型事件本身不参与容器自动解析流程,靠手动取或事件系统桥接才能享受依赖注入的好处。











