Laravel: 监听模型的保存或更新(在它们完成之后或之前)

85
我需要生成一个在save()或update()之后或之前调用的函数,但我不知道该怎么做。 我认为我需要从save()和update()中获取回调,但我不知道该怎么做。 谢谢。

1
请查看此链接 https://dev59.com/02Yr5IYBdhLWcg3wpLn9 - Anand Pandey
这个回答解决了你的问题吗?Laravel模型回调:保存后、保存前等 - Nico Haase
3个回答

203

在您的模型中,您可以添加一个boot()方法,允许您管理这些事件。

例如,有一个User.php模型:

class User extends Model 
{

    public static function boot()
    {
        parent::boot();

        self::creating(function($model){
            // ... code here
        });

        self::created(function($model){
            // ... code here
        });

        self::updating(function($model){
            // ... code here
        });

        self::updated(function($model){
            // ... code here
        });

        self::deleting(function($model){
            // ... code here
        });

        self::deleted(function($model){
            // ... code here
        });
    }

}

您可以在这里查看所有可用的事件:https://laravel.com/docs/5.2/eloquent#events


15
注意:当通过Eloquent进行批量更新时,已保存和更新的模型事件不会针对更新的模型触发。这是因为在执行批量更新时,实际上从未检索到这些模型。 - Fizk
1
你说得对。这仅适用于运行单个请求时,当处理批处理时,我建议循环遍历批处理以触发这些事件。 - Mauro Casas
2
一个快速有用的附注 @MauroCasas:你最好使用 booted 方法而不是 boot。这种方法适用于特定情况,并在 boot() 之后调用。这样做,你就不需要调用 parent::boot()。 - Romain 'Maz' BILLOIR

34

这仅在您的模型上发生事件后才起作用。

方法一,使用观察者

为您的模型创建一个观察者

php artisan make:observer UserObserver --model=User

这将在您的模型上创建一个事件观察器

class UserObserver
{
    /**
     * Handle the User "created" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function created(User $user)
    {
        //
    }

    /**
     * Handle the User "updated" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function updated(User $user)
    {
        //
    }

    /**
     * Handle the User "deleted" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function deleted(User $user)
    {
        //
    }

    /**
     * Handle the User "forceDeleted" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function forceDeleted(User $user)
    {
        //
    }
}

你必须在其中一个ServiceProvider的boot方法中注册此观察器,最好是AppServiceProvider。

// App\Providers\AppServiceProvider.php

public function boot()
{
    User::observe(UserObserver::class);
}

方法二,使用闭包

您可以在模型的静态启动方法中注册自定义事件。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The "booted" method of the model.
     *
     * @return void
     */
    protected static function boot()
    {
        parent::boot();
        static::created(function ($user) {
            //
        });
    }
}

可用的可观察事件

// Illuminate\Database\Eloquent\Concerns

/**
 * Get the observable event names.
 *
 * @return array
 */
public function getObservableEvents()
{
    return array_merge(
        [
            'retrieved', 'creating', 'created', 'updating', 'updated',
            'saving', 'saved', 'restoring', 'restored', 'replicating',
            'deleting', 'deleted', 'forceDeleted', 'trashed'
        ],
        $this->observables
    );
}

Laravel文档中的注意事项

通过Eloquent进行批量更新时,对于已更新的模型,将不会触发保存、已保存、更新和已更新的模型事件。这是因为在进行批量更新时,实际上并没有检索到这些模型。

这意味着当您直接更新数据库中的用户信息时,不会触发任何事件:

User::where(...)->update(['name' => "ABC"]);

你必须手动从数据库中获取每个用户并更新它,以触发事件,这对性能来说非常糟糕。

User::where(...)->each(function($user) {
   $user->update(['name' => "ABC"]);
});

除非您知道表格具有固定且较少的行数,否则不要这样做...


17
使用此命令创建提供程序。
php artisan make:provider ProviderClassName

然后在启动函数中定义模型的回调函数。

Model::created(function($model){
  //Do you want to do
});

可用的回调函数列表:

Model::creating(function($model){});
Model::updated(function($model){});
Model::updating(function($model){});
Model::deleted(function($model){});
Model::deleting(function($model){});
Model::saving(function($model){});
Model::saved(function($model){});

2
也包括 saving() 和 saved()。 - Mina Abadir
不需要完全新的 ServiceProvider,您可以使用 AppServiceProvider 进行应用程序定制。 - Mina Abadir
如果我将此函数添加到注册函数而不是引导函数中,有什么区别? - Roy Ryando
还有retrieved()restoring()restored()replicating()forceDeleted() - MacroMan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接