Framework: Model's push method does not work with new relations

Created on 8 Oct 2015  路  12Comments  路  Source: laravel/framework

The push method feels as though it should be able to save any new relations added to the model. However it can't as the foreign id isn't set.
See the following code as an example:

$user = new User(['name' => 'Mike']);
$post = new Post(['title' => 'Push is broken']);
$user->posts->add($$post);
$user->push();

Most helpful comment

Thanks, I also tried something and got something similar. Combined them with your result with a few tweaks:

  • Convert attributes to relations when possible (when you call $user->posts = [..] on a new model)
  • Convert arrays to models (so you can pass an array instead of models)
  • Use the save() method instead of the keys

See https://gist.github.com/barryvdh/f963f5c67d5cfc23357f1a81b3aad56a

Can do something like this:

$user = new User;
    $user->name = 'Barry';
    $user->email = str_random();
    $user->password = str_random();

    $post = new Post;
    $post->title = 'Test 1';
    $post->body = 'Lorem ipsum';

    $user->posts[] = $post;
    $user->posts[] = [
        'title'  => 'Test 2',
        'body' => 'from array',
    ];

    $user->pushAll();

The only thing which could be 'breaking' is the automatic changing of attributes -> relations, so might make an extra method or add a better check?

All 12 comments

I have faced this issue many times before, I'll try to find a solution for this.

You are just adding a model to a loaded collection of the relationship result. You should use one of these method to insert related models: http://laravel.com/docs/5.1/eloquent-relationships#inserting-related-models

@lukasgeiter yes, but in that case it'll probably throw an error as well since this is a new user. I think the method push should do the all the work.

You could probably do something like $user->setRelation('posts', collect($post)); $user->push();
Also I don't see why you can't just save the user before inserting relationships?

@lukasgeiter of course you can, but it's not intuitive and you could delegate that to the ORM.

Give me a couple of days and I'll present a possible solution for this "issue".

I came here to post this exact issue.

@lucasgeiter I have a model where a number of mutators need to update or create a related model. The related model requires multiple fields to be set before validation will allow it to be saved to the database, so either the validation or mutators have to go.

@sileence Have you made any progress on a solution? Is there any assistance I could provide?

@sileence Did you ever find a clean solution for this?

@barryvdh yes, first you need to save the belongsTo relations, then the main model, and finally the hasMany relations.

I set a reminder to work on this when I get home (about 4 hours from now).

Ok working on this again @barryvdh

narrowing the problem:

https://github.com/sileence/eloquent_push_tests/blob/master/tests/EloquentPushTest.php

The unit tests pass because they don't have FK as these integration tests do.

@barryvdh the code is "primitive" but the tests are passing, I can refactor and PR later:

https://github.com/sileence/eloquent_push_tests/blob/master/app/Model.php

https://github.com/sileence/eloquent_push_tests/blob/master/tests/EloquentPushTest.php

cc @taylorotwell

Thanks, I also tried something and got something similar. Combined them with your result with a few tweaks:

  • Convert attributes to relations when possible (when you call $user->posts = [..] on a new model)
  • Convert arrays to models (so you can pass an array instead of models)
  • Use the save() method instead of the keys

See https://gist.github.com/barryvdh/f963f5c67d5cfc23357f1a81b3aad56a

Can do something like this:

$user = new User;
    $user->name = 'Barry';
    $user->email = str_random();
    $user->password = str_random();

    $post = new Post;
    $post->title = 'Test 1';
    $post->body = 'Lorem ipsum';

    $user->posts[] = $post;
    $user->posts[] = [
        'title'  => 'Test 2',
        'body' => 'from array',
    ];

    $user->pushAll();

The only thing which could be 'breaking' is the automatic changing of attributes -> relations, so might make an extra method or add a better check?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lzp819739483 picture lzp819739483  路  3Comments

SachinAgarwal1337 picture SachinAgarwal1337  路  3Comments

ghost picture ghost  路  3Comments

YannPl picture YannPl  路  3Comments

iivanov2 picture iivanov2  路  3Comments