【问题标题】:Laravel mass update , still fire eventLaravel 大规模更新,依然火的事件
【发布时间】:2019-10-11 16:35:53
【问题描述】:

如文档中所述,laravel 不会在批量更新/插入/删除时触发事件。 https://laravel.com/docs/5.8/eloquent#events

它为此使用了 Builder,并且不会触发事件。

例如,有没有办法在大规模更新后仍然可以触发事件?我只需要查询生成器自己提取所需的信息(日志目的)。

【问题讨论】:

  • @VikashPathak :谢谢,我找到了那个,但我将如何在模型中实现它?因此,当调用查询生成器 Update() 时,它会触发一个事件。例如:$model->where(something)->update([]); >> 火灾事件。
  • 如果你想为批处理请求做...你将不得不触发自定义事件。

标签: laravel eloquent


【解决方案1】:

这实际上是可能的,但是您必须扩展 Eloquent 构建器,覆盖更新/插入方法并将事件发送到那里。 一直在玩它...需要工作,但基本思想如下:

class Test extends Model
{
    protected $guarded = [];

    public $dispatchesEvents = [
        'saved' => SavedTest::class
    ];


    /**
     * INCLUDE this as a trait in your model.
     * Overwrite the eloquentBuilder.
     *
     * @param  \Illuminate\Database\Query\Builder  $query
     * @return \Illuminate\Database\Eloquent\Builder|static
     */
    public function newEloquentBuilder($query)
    {

        return new TestBuilder($query);
    }


}

扩展 eloquent builder...

class TestBuilder extends Builder
{

    /**
     * Update a record in the database and fire event.
     *
     * @param  array  $values
     * @return int
     */
    public function update(array $values)
    {

        // normal eloquent behavior.
        $result =$this->toBase()->update($this->addUpdatedAtColumn($values));

        /*
         * Fire event.
         */
        if($result){
            if( $event = Arr::get($this->model->dispatchesEvents,'saved')){

                 // at the attributes.
                $this->model->fill($this->addUpdatedAtColumn($values));

                $queryBuilder =$this->toBase();

                event(new $event($this->model,$queryBuilder));
            }

        }

    }

    public function insert(array $values)
    {

       // same idea..
    }
}

事件类:

class SavedTest
{
    use SerializesModels;
    public $model;
    public $query;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct($model,$query =null)
    {
        $this->model = $model;
        $this->query = $query;
    }


}

听者。

class SavedTestEvent
{


    /**
     * Create the event listener.
     *
     * 
     */
    public function __construct()
    {

    }

    /**
     * Handle the event.
     *
     * @param  object  $event
     * @return void
     */
    public function handle($event)
    {

        // The model , with the attributes.
        dump($event->model);

       // the query builder , you could extract the wheres or whatever to build your own log for it.
      dump($event->query); 


    }
}

【讨论】:

  • 能否获取更新记录时用到的主键或其他参数?
【解决方案2】:

@Paolo 在批处理请求中不会归档您必须对单个记录执行操作的事件.. 就像

Analytic::where('id', '>', 100)->get()->each(function($analytic) {
    $analytic->delete();
});

【讨论】:

  • @Paolo_Mulder 这有帮助吗?
  • @Viksah Pathak :感谢您的回复伙伴,但这意味着要更改当前项目的大量代码。我设法扩展了我在下面发布的想法,它运行良好,并且减少了很多查询。到目前为止一切顺利,仍在测试所有可能的问题。
  • 如果表中有很多记录,比如一百万行,这个解决方案可能需要很长时间。您可能会出现内存不足错误,您可以使用 chunkById 来检查内存问题,但这将花费大量时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-28
  • 2020-09-02
  • 2018-12-27
相关资源
最近更新 更多