【问题标题】:Is it possible to temporarily disable event in Laravel?是否可以暂时禁用 Laravel 中的事件?
【发布时间】:2015-06-07 02:31:20
【问题描述】:

我在“已保存”模型事件中有以下代码:

Session::flash('info', 'Data has been saved.')` 

所以每次保存模型时,我都会收到一条消息通知用户。问题是,有时我只需要更新一个像“状态”这样的字段或增加一个“计数器”,而我不需要为此发送消息。那么,是否可以暂时禁用触发模型事件?或者有没有像$model->save() 这样不会触发“已保存”事件的 Eloquent 方法?

【问题讨论】:

    标签: laravel laravel-4


    【解决方案1】:

    Laravel 8.x 和 9.x 的解决方案

    使用 Laravel 8 变得更加容易,只需使用 saveQuietly 方法:

    $user = User::find(1);
    $user->name = 'John';
    
    $user->saveQuietly();
    
    

    Laravel 8.x docs
    Laravel 9.x docs


    Laravel 7.x、8.x 和 9.x 的解决方案

    在 Laravel 7(或 8 或 9)上,按照以下方式包装您的引发事件的代码:

    $user = User::withoutEvents(function () use () {
        $user = User::find(1);
        $user->name = 'John';
        $user->save();
    
        return $user;
    });
    

    Laravel 7.x docs
    Laravel 8.x docs
    Laravel 9.x docs


    Laravel 5.7 到 6.x 版本的解决方案

    以下解决方案适用于 Laravel 5.7 到 6.x 版本,对于旧版本,请检查答案的第二部分。

    在您的模型中添加以下函数:

    public function saveWithoutEvents(array $options=[])
    {
        return static::withoutEvents(function() use ($options) {
            return $this->save($options);
        });
    }
    

    然后在没有事件的情况下保存如下:

    $user = User::find(1);
    $user->name = 'John';
    
    $user->saveWithoutEvents();
    

    更多信息请查看Laravel 6.x documentation


    Laravel 5.6 及更早版本的解决方案

    在 Laravel 5.6(和以前的版本)中,您可以禁用并再次启用事件观察器:

    // getting the dispatcher instance (needed to enable again the event observer later on)
    $dispatcher = YourModel::getEventDispatcher();
    
    // disabling the events
    YourModel::unsetEventDispatcher();
    
    // perform the operation you want
    $yourInstance->save();
    
    // enabling the event dispatcher
    YourModel::setEventDispatcher($dispatcher);
    

    更多信息请查看Laravel 5.5 documentation

    【讨论】:

    • 这个答案在编写时很棒,但现在有一种更简洁的方法,using withoutEvents() below :)
    • @Dan 这太棒了。我不知道saveQuietly(),但为我工作。感谢您在 Laravel 更改时保持更新这篇文章!你大男人,丹!
    【解决方案2】:

    有一个不错的解决方案,来自 Taylor 的 Twitter 页面:

    将此方法添加到您的基础模型中,或者如果您没有,请创建一个特征,或将其添加到您当前的模型中

    public function saveQuietly(array $options = [])
    {
        return static::withoutEvents(function () use ($options) {
            return $this->save($options);
        });
    }
    

    然后在您的代码中,每当您需要保存模型而不触发事件时,只需使用以下代码:

    $model->foo = 'foo';
    $model->bar = 'bar';
    
    $model->saveQuietly();
    

    非常优雅和简单:)

    【讨论】:

    【解决方案3】:

    调用模型对象然后调用 unsetEventDispatcher 之后你可以做任何你想做的事,而不用担心事件触发

    喜欢这个:

        $IncidentModel = new Incident;
        $IncidentModel->unsetEventDispatcher();
    
        $incident = $IncidentModel->create($data);
    

    【讨论】:

      【解决方案4】:

      要为最终在这里寻找解决方案的任何人回答问题,您可以使用 unsetEventDispatcher() 方法在实例上禁用模型侦听器:

      $flight = App\Flight::create(['name' => 'Flight 10']);
      $flight->unsetEventDispatcher();
      $flight->save(); // Listeners won't be triggered
      

      【讨论】:

      • 创建和创建事件触发器不会在第一行触发吗??
      • 你说得很好;不过,就我的目的而言,我对抑制“保存”事件不被触发很感兴趣,这确实起到了作用。
      • 我猜是这样的:)
      • @AndySoell 我是否必须在保存后运行 setEventDispatcher 才能再次启用事件?我试图这样做 $flight->setEventDispatcher();但我得到了:函数 Illuminate\Database\Eloquent\Model::setEventDispatcher() 的参数太少,通过了 0 ... 完成后如何再次恢复事件?
      • @nikocraft 如果我自己没有尝试过,我会尝试做一个$flight->fresh()$flight->refresh(),理论上这会给你的变量一个模型实例的新副本。我想这意味着重新启用观察者。
      【解决方案5】:

      您不应该将会话闪烁与模型事件混为一谈 - 模型没有责任在发生某些事情时通知会话。

      最好让你的控制器在保存模型时调用 session flash。

      这样您就可以控制何时实际显示消息 - 从而解决您的问题。

      【讨论】:

      • 感谢您的回答。一开始我以为它可以自动化flash消息所以我不需要重复把它放在控制器中,至于模型的责任我认为通知会话的不是模型,模型只是触发事件,它不知道事件的侦听器在做什么,是吗?不过不管怎样,我觉得还是按照你说的放到控制器里面比较好,因为好像没有办法避免这个问题。
      【解决方案6】:

      在 laravel 7.x 中,您可以像这样简单地做到这一点

      use App\User;
      
      $user = User::withoutEvents(function () use () {
          User::findOrFail(1)->delete();
      
          return User::find(2);
      });
      

      Laravel 7.x Muting Events documentation中查看更多信息

      【讨论】:

        【解决方案7】:

        在 laravel 8.x 中:

        保存没有事件的单个模型

        有时您可能希望“保存”给定模型而不引发任何事件。您可以使用 saveQuietly 方法完成此操作:

        $user = User::findOrFail(1);
        
        $user->name = 'Victoria Faith';
        
        $user->saveQuietly();
        

        See Laravel docs

        【讨论】:

          猜你喜欢
          • 2011-09-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-24
          • 1970-01-01
          相关资源
          最近更新 更多