codebug
codebug

Reputation: 723

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?

Upvotes: 58

Views: 74069

Answers (9)

Morteza Rajabi
Morteza Rajabi

Reputation: 2913

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

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

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

Then in your 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 :)

Upvotes: 49

Luc Wollants
Luc Wollants

Reputation: 890

The only thing that worked for me was using the trait WithoutEvents. This will be executed inside the setUp method and does prevent any dispatch you have added to the code.

Upvotes: 0

Sergi
Sergi

Reputation: 140

Although it's a long time since the question, I've found a way to turn off all events at once. In my case, I'm making a migration script, but I don't want any event to be fired (either from Eloquent or any other).

The thing is to get all the events from the Event class and remove them with the forget method.

Inside my command:

$events = Event::getRawListeners();
foreach ($events as $event_name => $closure) {
    Event::forget($event_name);
}

Upvotes: 0

SpaceDogCS
SpaceDogCS

Reputation: 2968

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

Upvotes: 6

Dan
Dan

Reputation: 3584

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

Upvotes: 195

David Alvarez
David Alvarez

Reputation: 1286

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

Upvotes: 5

Marlon Bernal
Marlon Bernal

Reputation: 577

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

Upvotes: 14

ams
ams

Reputation: 806

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

Upvotes: 10

Laurence
Laurence

Reputation: 60068

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.

Upvotes: 4

Related Questions