Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to temporarily disable event in Laravel?

I have the following code in 'saved' model event:

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

so everytime the model is saved I can have a flash message to inform users. The problem is, sometimes I just need to update a field like 'status' or increment a 'counter' and I don't need a flash message for this. So, is it possible to temporarily disable triggering the model event? Or is there any Eloquent method like $model->save() that doesn't trigger 'saved' event?

like image 313
codebug Avatar asked Apr 02 '15 07:04

codebug


7 Answers

Solution for Laravel 8.x and 9.x

With Laravel 8 it became even easier, just use saveQuietly method:

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

$user->saveQuietly();

Laravel 8.x docs
Laravel 9.x docs


Solution for Laravel 7.x, 8.x and 9.x

On Laravel 7 (or 8 or 9) wrap your code that throws events as per below:

$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


Solution for Laravel versions from 5.7 to 6.x

The following solution works from the Laravel version 5.7 to 6.x, for older versions check the second part of the answer.

In your model add the following function:

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

Then to save without events proceed as follow:

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

$user->saveWithoutEvents();

For more info check the Laravel 6.x documentation


Solution for Laravel 5.6 and older versions.

In Laravel 5.6 (and previous versions) you can disable and enable again the event observer:

// 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);

For more info check the Laravel 5.5 documentation

like image 157
Dan Avatar answered Sep 28 '22 00:09

Dan


There is a nice solution, from Taylor's Twitter page:

Add this method to your base model, or if you don't have one, create a trait, or add it to your current model

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

Then in you code, whenever you need to save your model without events get fired, just use this:

$model->foo = 'foo';
$model->bar = 'bar';

$model->saveQuietly();

Very elegant and simple :)

like image 45
Morteza Rajabi Avatar answered Sep 28 '22 00:09

Morteza Rajabi


Call the model Object then call unsetEventDispatcher after that you can do whatever you want without worrying about Event triggering

like this one:

    $IncidentModel = new Incident;
    $IncidentModel->unsetEventDispatcher();

    $incident = $IncidentModel->create($data);
like image 22
Marlon Bernal Avatar answered Sep 28 '22 00:09

Marlon Bernal


To answer the question for anyone who ends up here looking for the solution, you can disable model listeners on an instance with the unsetEventDispatcher() method:

$flight = App\Flight::create(['name' => 'Flight 10']);
$flight->unsetEventDispatcher();
$flight->save(); // Listeners won't be triggered
like image 27
Andy Soell Avatar answered Sep 28 '22 01:09

Andy Soell


In laravel 8.x :

Saving A Single Model Without Events

Sometimes you may wish to "save" a given model without raising any events. You may accomplish this using the saveQuietly method:

$user = User::findOrFail(1);

$user->name = 'Victoria Faith';

$user->saveQuietly();

See Laravel docs

like image 36
David Alvarez Avatar answered Sep 28 '22 01:09

David Alvarez


In laravel 7.x you can do that as easy as

use App\User;

$user = User::withoutEvents(function () {
    User::findOrFail(1)->delete();

    return User::find(2);
});

See more in Laravel 7.x Muting Events documentation

like image 36
SpaceDogCS Avatar answered Sep 28 '22 00:09

SpaceDogCS


You shouldnt be mixing session flashing with model events - it is not the responsibility of the model to notify the session when something happens.

It would be better for your controller to call the session flash when it saves the model.

This way you have control over when to actually display the message - thus fixing your problem.

like image 36
Laurence Avatar answered Sep 28 '22 00:09

Laurence