Crud: Model Observer not triggering on updated or saved

Created on 15 Nov 2016  路  8Comments  路  Source: Laravel-Backpack/CRUD

Hi,

I'm trying to add a model observer for a CRUD model:

namespace App\Observers;
use App\Admin;


class AdminObserver
{

    /**
     * Listen to the Admin created event.
     *
     * @param  Admin  $admin
     * @return void
     */
    public function created(Admin $admin)
    {
        dd('created');
    }

    public function updated(Admin $admin)
    {
        dd('updated');
    }
}

Created works fine and triggers when I add a new admin.
However the 'updated' listener never seems to get triggered when updating an entry. Nor does 'saved'.

I've noticed the Laravel docs say:

When issuing a mass update via Eloquent, the saved and updated model events will not be fired for the updated models. This is because the models are never actually retrieved when issuing a mass update.

Is this why the 'updated' listener doesn't get called? Is there any way around this?

Many thanks.

Most helpful comment

Hi guys,

@indra1 , actually the code you sent proves it is NOT a bulk operation :-) We do findOrFail() first. So events should work fine, I've used them in a few projects.

@Eminee , as far as I know the updating and updated events are only fired if an edit was made. If you submit the edit form without actually modifying anything, Eloquent will notice that and it will not execute an "UPDATE" sql command, so it will no longer trigger the event either. Please also test by editing something in the form. Does it fix it for you?

But it's very odd that saved doesn't work for you. I just tried all events again:

  • on the Create form, it triggered the events in this order: saving, creating, created, saved;
  • on the Edit form, it triggered: saving, updating, updated, saved when I modified a field;
  • on the Edit form, it triggered: saving, saved when I didn't modify anything;
  • on pressing the Delete button, it triggered: deleting, deleted;

Soo... seems to be working fine.

Are you sure you didn't have a typo when you tried saved? Can you try again and share the observer if it doesn't work?

Cheers!

All 8 comments

@tabacitu any ideas? I've just had a go myself and can confirm its not firing, unless we're both doing something wrong? Might need to manually trigger it if not?

@OwenMelbz @Eminee
Backpack update looks like mass update to me https://github.com/Laravel-Backpack/CRUD/blob/master/src/PanelTraits/Update.php

I guess you can overwrite the update method like this in your controller:

 public function update(UpdateRequest $request)
    {
 // triger updated event in this method
        $result =  parent::updateCrud($request);
// triger 
 }

or if you want to go further:
this is the updateCrud Method. Overwrite it and have fun:

 public function updateCrud(UpdateRequest $request = null)
    {
        $this->crud->hasAccessOrFail('update');

        // fallback to global request instance
        if (is_null($request)) {
            $request = \Request::instance();
        }

        // replace empty values with NULL, so that it will work with MySQL strict mode on
        foreach ($request->input() as $key => $value) {
            if (empty($value) && $value !== '0') {
                $request->request->set($key, null);
            }
        }

        // update the row in the db
        $this->crud->update($request->get($this->crud->model->getKeyName()),
                            $request->except('redirect_after_save', '_token'));

        // show a success message
        \Alert::success(trans('backpack::crud.update_success'))->flash();

        return \Redirect::to($this->crud->route);
    }

Hi guys,

@indra1 , actually the code you sent proves it is NOT a bulk operation :-) We do findOrFail() first. So events should work fine, I've used them in a few projects.

@Eminee , as far as I know the updating and updated events are only fired if an edit was made. If you submit the edit form without actually modifying anything, Eloquent will notice that and it will not execute an "UPDATE" sql command, so it will no longer trigger the event either. Please also test by editing something in the form. Does it fix it for you?

But it's very odd that saved doesn't work for you. I just tried all events again:

  • on the Create form, it triggered the events in this order: saving, creating, created, saved;
  • on the Edit form, it triggered: saving, updating, updated, saved when I modified a field;
  • on the Edit form, it triggered: saving, saved when I didn't modify anything;
  • on pressing the Delete button, it triggered: deleting, deleted;

Soo... seems to be working fine.

Are you sure you didn't have a typo when you tried saved? Can you try again and share the observer if it doesn't work?

Cheers!

Thanks for your reply @tabacitu, you are completely right - it was because we weren't editing any data. I'm not sure why saved didn't work though, must have been my mistake.

Thanks for your help!

Glad to help.

Cheers!

I'm really sorry to remark on such an old issue @tabacitu but I honestly cannot understand how to properly set a field when updating a record.

Eg: On a Phrase model, combine/adjust text_a and text_b and save in text_full column.

I've tried the following:

  1. Following the 4.1 docs precisely. $this->crud->request->request->add(['text_full' => ...]) results in Cannot access protected property Backpack\CRUD\app\Library\CrudPanel\CrudPanel::$request

  2. Following a suggestion from the docs and here to use Eloquent events, the update event never seems to fire no matter what. (I've added a dd to the the updated method of a PhraseObserver and added this to the AppServiceProvider.

  3. Following a suggestion from #51 results in Method App\Http\Controllers\Admin\PhraseCrudController::storeCrud does not exist.

I'm not sure how relevant these issues are as they refer to much older versions of Backpack, but a solution for problem 1 or a clearer documentation for how to implement the event observer would be really helpful, I'm so

Ok, finally, after a tip from a user in the gitter that you're not able to access the $request from CrudPanel class anymore and to inherit the variable $request = request(); which addresses points 1 and 3 from above.

Then, with all old examples pointing to parent::updateCrud which doesn't work, I finally found the solution in the 4.0 upgrade notes

It's particularly confusing that the documentation also changes between 4.0 and 4.1 thus feeling up to date/correct: $this->crud->request->request->add(['author_id'=> backpack_user()->id]); which, from what I can understand, is incorrect?

Can the documentation please be updated to reflect the correct way to do this?

This also sadly doesn't explain why the Eloquent events weren't being fired.

Ugh. Sorry for the frustration this must have cause you @alancwoo - indeed, this is something that might not be clearly documented, I'll take some time to re-evaluate how we explain this, and update the docs. Thanks a lot!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AlexanderWM picture AlexanderWM  路  3Comments

jorgepires picture jorgepires  路  3Comments

sokvebolkol picture sokvebolkol  路  3Comments

sseggio picture sseggio  路  3Comments

deepaksp picture deepaksp  路  3Comments