Why laravel model duplicates set of data and how (if possible) to have only one set of data? Why laravel model duplicates set of data and how (if possible) to have only one set of data? laravel laravel

Why laravel model duplicates set of data and how (if possible) to have only one set of data?


While it's hard to get a good example, it allows you to set attributes before definitely saving them. Probably good if you go through many functions and finally check if everything has been set correctly for final save without the need to store everything in separate variables.

Very small example:

$user = User::find(1);print_r($user);$user->name = 'John Doe';print_r($user);$user->save();print_r($user());

Returns something like:

First print:

[attributes:protected] => Array(   [id] => 1   [name] => 'Jimmy Doe'   ...)[original:protected] => Array(   [id] => 1   [name] => 'Jimmy Doe'   ...)

Second print:

[attributes:protected] => Array(   [id] => 1   [name] => 'John Doe'   ...)[original:protected] => Array(   [id] => 1   [name] => 'Jimmy Doe'   ...)

Thrid print:

[attributes:protected] => Array(   [id] => 1   [name] => 'John Doe'   ...)[original:protected] => Array(   [id] => 1   [name] => 'John Doe'   ...)

Only after the save() the data is actually being saved into the DB.

The Eloquent's syncOriginal() is fired up when a model is save()'d:

/** * Sync the original attributes with the current. * * @return $this */public function syncOriginal(){    $this->original = $this->attributes;    return $this;}


The original data is stored in order to allow the model to perform dirty checking. Dirty checking is used internally to handle database updates.

If a model is not dirty and you try to save it, no update will be performed. If a model is dirty and you try to save it, only those fields that are dirty will be updated.

If you really wanted to get rid of this, you could override the syncOriginal() and syncOriginalAttribute() methods on the model. If you did this, though, it would mean that the model will always be considered dirty. getDirty() will always return all the attributes, and isDirty() will always return true.

If you use timestamps, you will also need to override the updateTimestamps() method, otherwise your updated_at and created_at fields would never get set.

class Feedback extends Model{    // ...    public function syncOriginal()    {        return $this;    }    public function syncOriginalAttribute($attribute)    {        return $this;    }    protected function updateTimestamps()    {        $time = $this->freshTimestamp();        $this->setUpdatedAt($time);        if (! $this->exists) {            $this->setCreatedAt($time);        }    }    // ...}

There may be other repercussions that aren't immediately apparent while reviewing the code.

Having said all this, though, if you're having this concern about memory, you may need to have a second thought about your approach and what you're trying to do. Do you really need to load 1000's of feedback all at once? Is this an operation that can be chunked? Is this work that would be better served by individual jobs in a queue? etc...


This should not be an issue considering how PHP works internally. Unless the 'attributes' are not modified, 'attributes' is just a pointer to the 'original' (or the other way around), so having both arrays takes up nearly the same amount of memory as having just one of them. This is why memory usage does not change when you do toArray().

Please see this link for details: http://blog.ircmaxell.com/2014/12/what-about-garbage.html