wasChanged() vs wasRecentlyCreated - Laravel Tips
Tags: laravel, tips, webdev, development
Published: 2024-01-02 10:32:09

Let's start with a simple model like this:

```php
class MyModel extends Model
{
    protected $fillable = [
        'name'
    ];

    protected static function booted(): void
    {
        static::created(function ($model) {
            $model->dumpEvent('CREATED');
        });

        static::updated(function ($model) {
            $model->dumpEvent('UPDATED');
        });

        static::saved(function ($model) {
            $model->dumpEvent('SAVED');
        });
    }

    public function dumpEvent(string $event): void
    {
        dump([
            'event' => $event,
            'wasChanged()' => $this->wasChanged(),
            'wasRecentlyCreated' => $this->wasRecentlyCreated
        ]);
    }
}
```

Let’s create a new model:

```php
$model = MyModel::create(['name' => 'ABC']);
```

We get:

```php
array:3 [ // app/Models/MyModel.php:30
  "event" => "CREATED"
  "wasChanged()" => false      // <-- ❗
  "wasRecentlyCreated" => true
]
array:3 [ // app/Models/MyModel.php:30
  "event" => "SAVED"
  "wasChanged()" => false      // <-- ❗
  "wasRecentlyCreated" => true
]
```

NOTE:

- ❗`wasChanged()` is `false`

---

If we call `save()` without changes on the same model instance:

```php
// $model = MyModel::create(['name' => 'ABC']);
// ...
// ... no changes on `$model` fields

$model->save();
```

We get:

```php
array:3 [ // app/Models/MyModel.php:30
  "event" => "SAVED"
  "wasChanged()" => false
  "wasRecentlyCreated" => true
]
```

NOTE: 

- it will be triggered the `saved()` event
- but it will not be triggered the `updated()` event
- `wasRecentlyCreated` is still `true` (remember: it’s the same `$model` instance)

---

Now, let’s make some changes, always on the same model instance:

```php
// $model = MyModel::create(['name' => 'ABC']);
// ...

$model->name = 'ABC new';
$model->save();
```

We get:

```php
array:3 [ // app/Models/MyModel.php:30
  "event" => "UPDATED"
  "wasChanged()" => true
  "wasRecentlyCreated" => true // <-- ❗
]
array:3 [ // app/Models/MyModel.php:30
  "event" => "SAVED"
  "wasChanged()" => true
  "wasRecentlyCreated" => true // <-- ❗
]
```

NOTE:

- `wasChanged()` is `true` (OK, we expected it to be)
- ❗`wasRecentlyCreated` is still `true` (remember: it’s the same `$model` instance)

---

What happens after a `refresh()`?

```php
// $model = MyModel::create(['name' => 'ABC']);
// ...

// $model->name = 'ABC new';
// $model->save();

$model->refresh();
$model->save();
```

We get again:

```php
array:3 [ // app/Models/MyModel.php:30
  "event" => "SAVED"
  "wasChanged()" => true       // <-- ❗
  "wasRecentlyCreated" => true // <-- ❗
]
```

So even after a `refresh()`, it doesn’t change the internal status for the `wasChanged()` or `wasRecentlyCreated`!

---

## Conclusion

In general, between different requests, reloading a model from the DB does not generate problems. But the behavior of `wasChanged()` and `wasRecentlyCreated` can become bizarre in the same request, i.e. on the same instance of the newly created model, especially if the model is configured to trigger events in the `saved()` method, when something has actually changed, for example:

```php
protected static function booted(): void
{
    static::saved(function ($model) {
        if (! $model->wasChanged() && ! $model->wasRecentlyCreated) {
            return; // no changes and no new record
        }

        event(new MyCustomEvent(
            $model->wasRecentlyCreated ? 'mymodel.new' : 'mymodel.updated'),
            $model
        );
    });
}
```

---

✸ Enjoy your coding!

&nbsp;

###### If you liked this post, don't forget to add your Follow to my profile!

{% user tonyjoe %}

---

###### *If you want to preview my content, [Subscrive to my Newsletter](https://tonyjoe.dev/newsletter)*!