Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

It is convenient that laravel model provides a method that it can return results from another associated table.

For example, I have a table called item and another table called feedback, where the feedback table stores feedback of an item in the item table. So, to get the all feedback of item with id 1, I will do:

Item::find(1)->feedback;

And the following this the printout of the object returned.

Illuminate\Database\Eloquent\Collection Object
(    [items:protected] => Array
       (
           [0] => Feedback Object
               (
                   [table:protected] => feedback
                   [connection:protected] => 
                   [primaryKey:protected] => id
                   [perPage:protected] => 15
                   [incrementing] => 1
                   [timestamps] => 1
                   [attributes:protected] => Array
                       (
                           [id] => 1
                           [rma_id] => 3
                           [item_id] => 8
                           [quo_id] => 0
                           [case_id] => i2eM20160120
                           [line_no] => 000001
                           [content] => test
                           [status] => sent
                           [read] => 0
                           [sender] => Tester
                           [created_at] => 2016-01-20 18:03:44
                           [updated_at] => 2016-01-20 18:03:44
                       )

                   [original:protected] => Array
                       (
                           [id] => 1
                           [rma_id] => 3
                           [item_id] => 8
                           [quo_id] => 0
                           [case_id] => i2eM20160120
                           [line_no] => 000001
                           [content] => test
                           [status] => sent
                           [read] => 0
                           [sender] => Tester
                           [created_at] => 2016-01-20 18:03:44
                           [updated_at] => 2016-01-20 18:03:44
                       )

                   [relations:protected] => Array
                       (
                       )

                   [hidden:protected] => Array
                       (
                       )

                   [visible:protected] => Array
                       (
                       )

                   [appends:protected] => Array
                       (
                       )

                   [fillable:protected] => Array
                       (
                       )

                   [guarded:protected] => Array
                       (
                           [0] => *
                       )

                   [dates:protected] => Array
                       (
                       )

                   [touches:protected] => Array
                       (
                       )

                   [observables:protected] => Array
                       (
                       )

                   [with:protected] => Array
                       (
                       )

                   [morphClass:protected] => 
                   [exists] => 1
               )

       )

)

It works fine, and it shows that there is only one feedback on item with id 1.

What concerns me is that the dataset is duplicated in [attributes:protected] and [original:protected]. This is just a testing case and the real case will consist of thousands of feedback and having a duplicated dataset is a huge waste of memory. The dataset is not duplicated if I am using the DB::table('table_name') approach, but that is much less convenient.

Why does laravel need to duplicate the data in model?

And is there a way to make it return only one set of data?

Currently I am using ->toArray() to trim down the unnecessary data right after the query, but the memory usage is still there because laravel is still creating that set of data.

like image 264
cytsunny Avatar asked Jan 20 '16 11:01

cytsunny


1 Answers

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;
}
like image 136
Th3Alchemist Avatar answered Oct 18 '22 18:10

Th3Alchemist