How do you insert related polymorphic models in Laravel 4

11,061

save method on the MorphMany takes related Model as param, not an array.

It will always correctly set the foreign key, and model type for polymorphic relations. Obviously you need to save the parent model first.

// Meta morphTo(User)
$user = User::find($id);

$meta = new Meta([...]);
$user->meta()->save($meta);

// or multiple
$user->meta()->saveMany([new Meta([...], new Meta[...]);

attach on the other hand is different method that works on belongsToMany and m-m polymorphic relations and it does not do the same, but those relations also use save.

// User belongsToMany(Category)
$user = User::find($id);
$user->categories()->save(new Category([...]));

// but attach is different
$user->categories()->attach($catId); // either id

$category = Category::find($catId);
$user->categories()->attach($category); // or a Model

// this will not work
$user->categories()->attach(new Category([...]));
Share:
11,061
Anthony
Author by

Anthony

Sometimes I just wish the code would write itself. Until then, here I am...

Updated on June 19, 2022

Comments

  • Anthony
    Anthony almost 2 years

    In Laravel 4 I have a "Meta" model that can be associated to any object via an "object_id" and "object_type" property. For example:

    id: 1
    object_id: 100
    object_type: User
    key: favorite_ice_cream
    value: Vanilla
    

    I have this working correctly via morphTo() and morphMany() as described in http://laravel.com/docs/eloquent#polymorphic-relations, so I can pull the user and all of his meta via:

    $user = User::with('meta')->find(100);

    What I'm trying to figure out now is: Is there an easy way to save meta to my user? As in:

    $user = User::find(100);
    $user->meta()->save(['key' => 'hair_color', 'value' = 'black']);
    

    Whatever does the saving would need to properly set the object_id and object_type on the meta. Since I've defined the relationships in the models, I'm not sure if that would be done automatically or not. I randomly tried it a few different ways but it crashed each time.

    • Jarek Tkaczyk
      Jarek Tkaczyk almost 10 years
      save method on the MorphMany takes related Model as param, not array. And 'crashed' doesn't mean anything, so be precise
    • Anthony
      Anthony almost 10 years
      If I create an array of Meta models and pass it to saveMany(), will saveMany automatically set the object_id and object_type properties? Or do I have to do that manually when I create the Meta objects? I was hoping that since I've already defined the relationship between Meta and User, and it knows how to retrieve Meta off of a User, that there would be a way to put Meta back into the User without having to manually set $meta->object_type = 'User' before doing $user->meta()->save($meta). Make sense?
    • user2094178
      user2094178 almost 10 years
      Do you mean $user->meta()->attach(1, ['key' => 'hair_color', 'value' => 'black']) does not achieve what you need?
    • Jarek Tkaczyk
      Jarek Tkaczyk almost 10 years
      Of course it will set the relation properly, so no need to manually set any of _type or _id
    • Anthony
      Anthony almost 10 years
      @deczo Ok, that makes sense. Thanks!
    • Anthony
      Anthony almost 10 years
      @user2094178 That looks interesting - I didn't understand the attach() method in the Laravel docs. What is the first argument for? Isn't it the ID of a pre-existing object?
    • user2094178
      user2094178 almost 10 years
      Yes, I guess it would have to be $meta = new Meta::create(['key' => 'hair_color', 'value' = 'black']); $user->meta()->save($meta). Do you want to relate any model through object_type? If yes, it looks like you are trying to achieve polymorphic-to-polymorphic, this is not available yet.
    • Anthony
      Anthony almost 10 years
      @user2094178 I'm using object_type to relate the model to another, since Meta can belong to anything; a User, a Post, a Comment, etc. I mainly wanted to know if $user->meta()->save($meta) would automatically stamp object_id and object_type during the save() process, or whether there was some other way to do it. I think I'm clear - thanks for the help!
    • Anthony
      Anthony almost 10 years
      @deczo - If you post your comment as an answer, I'll mark it.