1

I'm using Laravel and something is modifying a property before it's saved to the database.

In Database/Eloquent/Model.php I can modify the save() method like so:

dd($this->my_property);
if ($this->fireModelEvent('saving') === false) {
    return false;
}
dd($this->my_property);

In the first dd() the value is what I expected the second it has been modified.

I'm trying to go through Laravel's code but as best I can find it comes from a closure that looks like this when dd()'d:

Closure($event, $payload) {#4282 ▼
  class: "Illuminate\Events\Dispatcher"
  this: Illuminate\Events\Dispatcher {#35 …}
  use: {▼
    $listener: Closure(QueryExecuted $query) {#106 …}
    $wildcard: false
  }
  file: "my/path/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php"
  line: "453 to 459"
}

This isn't every helpful because Events/Dispatcher.php:453 is just a closure that calls $listener which is also a closure. Trying to debug it any more than that seems really difficult because you wind up catching earlier calls to this method not related to the eloquent update.

Is there any other way to list all listeners and there location to better understand where this property is being modified?

To be specific, I am updating a json array but it always merges the array rather than overwriting it for some reason. At present I have no idea if this is something in my codebase or in Laravel by default.

Example:

// ['one' => 10, 'two' => 20]
dump($model->counts);

$model->update(['counts' => ['three' => 30, 'four' => 40]]);

// ['one' => 10, 'two' => 20, 'three' => 30, 'four' => 40]
dump($model->counts);

// Expected result would be:
// ['three' => 30, 'four' => 40]
dump($model->counts);

So at some point the existing "counts" is being merged with old "counts" rather than overwriting it.

4
  • 1
    Do you have a mutator for your model? laravel.com/docs/11.x/eloquent-mutators You can also run php artisan model:show NameOfModel to see if there is an Observer that listens for model event. Commented Jun 13, 2024 at 16:12
  • model:show is interesting I hadn't seen that before. But unfortunately it just shows "Closure" and not where it's defined saving ......................................................................... Closure, Closure, App\Domain\Users\Observers\UsersObserver@saving Commented Jun 14, 2024 at 10:54
  • 1
    If it isn't the UsersObserver that is merging the array, see if any of the traits that you have added to the model adds a closure. For example running "grep -r creating app" gives me a result like app/Http/Traits/UsesUuid.php: static::creating(function ($model) { because I use the UsesUuid trait in one of my models. Commented Jun 14, 2024 at 11:01
  • Ah that's it it's coming from a trait! It seems like Laravel has an undocumented (as far as I can see) means of booting from a trait using $model->{'boot'.class_basename($trait)} and a package I had installed had implemented static::saving() within this method. Thankyou so much! If you added it as a proper answer I would accept it :) Commented Jun 14, 2024 at 11:11

1 Answer 1

1

In Laravel 11 there is a command that shows various information about your models and one of the information it provides is the Observers for that model. The command is model:show and you can invoke it running:

php artisan model:show

In case the Observer section doesn't mention a specific Observer class but it lists Closure then you need to revisit your model class. You could have a closure listed in there or you could have trait that defines such a closure. If it is a local trait you can find it by running a simple grep in the root of your project:

grep -r creating app

For example running the above command in a project of mine I get the result:

app/Http/Traits/UsesUuid.php:    static::creating(function ($model) {
...

because I use the UsesUuid trait in one of my models.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks in my case I had to look in the vendor folder using grep -r "static::saving" vendor

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.