Home » Errors » How to Fix Indirect Modification of Overloaded Property Has no Effect in Laravel

How to Fix Indirect Modification of Overloaded Property Has no Effect in Laravel

PHP programming language supports adding virtual properties to classes by using magic methods. You can define methods __get() and __set(), which will be called when somebody tries to access non-existent properties. Laravel Eloquent uses this feature to provide access to model attributes.

But the problem is that you can’t modify properties accessed by magic methods. You can get the value and set the value of the property, but not modify it. If you try to do this, you will get an Exception with the message “Indirect Modification of Overloaded Property Has no Effect”. You can encounter this when trying to add another element to an array field in the Eloquent model.

How to Fix This Issue?

Let’s create a model for tests. It will be the Article class with the settings field that is cast to an array:

class Article extends Model { protected $casts = [ "settings" => "array", ]; protected $attributes = [ "settings" => "[]", ]; //...... }

If you try to modify the field directly, you will get the exception:

$article->settings[] = "second";

The simplest way to fix this is to save the array into a local variable, add an element and set a result as the value for the settings field. For example:

$settings = $article->settings; $settings[] = "second"; $article->settings = $settings;

Also, you can write it in one line using array_merge():

$article->settings = array_merge($article->settings, ["second"]);

If you don’t like this approach, you can solve it in a more complicated way. You can cast the settings field to an object instead of an array, and interact with the properties of this object. First, create a DTO class for the settings:

class ArticleSettings { public array $list; public function __construct(array $list) { $this->list = $list; } public function toArray() { return $this->list; } }

Then, create a cast that will convert the array into the object of this class and revert it for saving in the database:

class ArticleSettingsCast implements CastsAttributes { public function get($model, $key, $value, $attributes) { return new ArticleSettings(json_decode($attributes["settings"])); } public function set($model, $key, $value, $attributes) { if (!$value instanceof MessagesBag) { throw new \InvalidArgumentException("Unsupported value!"); } return [ "settings" => $value->toArray(), ]; } }

Now, update the $casts array in the Article class:

protected $casts = [ "settings" => ArticleSettingsCast::class, ];

After this, you can modify the list property of settings object as you want. For example:

$article->settings->list[] = "green";

In additional, you can go a more object-oriented way: make the list property in the ArticleSettings private and add a method that can add values into the list array. It will work like this:


Wrapping Up

In this short article we have explained how to fix the exception when indirect modification of overloaded property has no effect in Laravel. Do you know a more efficient way to fix this? Tell us about it in the comments section below! May you also interested how to fix array to string conversion in Laravel? You can find detailed information in this article.

Your Reaction

Leave a Comment