2

I've seen that there is a function called wasChanged() where you can check if an attribute was changed on an update. Not is dirty, but was changed and persisted

However I'm trying to check this inside my model events boot function:

public static function boot()
{
    parent::boot();

    self::updated(function($appointment){

        if($appointment->wasChanged('appointment_date')) {
         // do something
        }

    });
}

This never works for me. Any ideas how I can check this?

the isDirty function has different behavior as that is used to check if an attribute was submitted in the request.

user3574492
  • 6,225
  • 9
  • 52
  • 105
  • I guess that previous (original) data is replaced by new (after save) and is not accessable in `updated` event. Did you try `updating` event? – IndianCoding May 26 '19 at 19:01
  • Yep, also doesn't work in `updating` – user3574492 May 26 '19 at 19:14
  • Are you sure that appointment_date actually had a different value before? If you do `$appointment->appointment_date = 'some-date'; $appointment->save()` then your event won't be called if the value was also 'some-date' before. – Rafał G. May 26 '19 at 19:22
  • @RafałG. Yes I change the date and submit the form. – user3574492 May 26 '19 at 19:24
  • 1
    I see you've found a solution. For future reference, starting with Laravel 5.7 your original code would work just fine. Earlier versions fire the `updated` event a little too early. Here's [5.5](https://github.com/laravel/framework/blob/5.5/src/Illuminate/Database/Eloquent/Model.php#L627) and here's [5.7](https://github.com/laravel/framework/blob/5.7/src/Illuminate/Database/Eloquent/Model.php#L728). When `syncChanges` is called after the event then `wasChanged` doesn't have the data it needs. – Rafał G. May 26 '19 at 19:57
  • For updating you can use `if ($user->username != $user->getOriginal('username'))` – Grant Nov 10 '22 at 07:23

3 Answers3

3

Although this post is old, I will insert my answer because the initial way in which you tried to solve this problem is the most correct way. You must have got it wrong before using the boot method. I use it continuously and I don't see the reason for the error. The code below continues to work. and just finished testing in 2021 with laravel 5, 7 and 8.

protected static function boot()
{
    parent::boot();

    self::updated(function ($user) {
        if($user->wasChanged('password')){
            $user->notify(new PasswordChanged($user));
        }
    });
}

The code below is updated and tested in 2021 and works perfectly for laravel 7 and 8.

protected static function booted()
{
    self::updated(function ($user) {
        if($user->wasChanged('password')){
            $user->notify(new PasswordChanged($user));
        }
    });
}

I put the two shapes that work very well. If you have problems similar to the above, the problem is probably beyond this scope.

2

After a bit of searching I found that there is a useful function called getOriginal() which returns an array of the original attribute values.

So I just had to access my attribute and do a compare:

$original_date = $appointment->getOriginal()['appointment_date'];

if($appointment->appointment_date != $original_date) {

 ...

}

Answer taken from here

user3574492
  • 6,225
  • 9
  • 52
  • 105
  • What is the context for "original"? Upon creation or just prior to the most recent save? – JR Lawhorne Nov 28 '20 at 15:46
  • Found the answer - "original" is what was loaded into the model when read from the DB. Even if you change and save several times, it doesn't update unless the model is reloaded from the DB. – JR Lawhorne Nov 28 '20 at 16:01
-2

U can check if save() method return true:

$object = new Model;
$object->attribute = $value;
if($object->save(){
 // attribute changed
}
Martin
  • 41
  • 6