How to save in a polymorphic relationship in Laravel?
Asked Answered
W

7

39

I'm reading the tutorial* on how to define many-to-many polymorphic relationships in Laravel but it doesn't show how to save records with this relationship.

In the their example they have

class Post extends Model
{
    /**
     * Get all of the tags for the post.
     */
    public function tags()
    {
        return $this->morphToMany('App\Tag', 'taggable');
    }
}

and

class Tag extends Model
{
    /**
     * Get all of the posts that are assigned this tag.
     */
    public function posts()
    {
        return $this->morphedByMany('App\Post', 'taggable');
    }

    /**
     * Get all of the videos that are assigned this tag.
     */
    public function videos()
    {
        return $this->morphedByMany('App\Video', 'taggable');
    }
}

I've tried saving in different ways but the attempts that makes most sense to me is:

$tag = Tag::find(1);
$video = Video::find(1);
$tag->videos()->associate($video);

or

$tag->videos()->sync($video);

None of these are working. Can anyone give me a clue on what I could try?

Walt answered 22/3, 2017 at 11:16 Comment(1)
What's the error?Barde
M
51

It's simple like that, see this section.

Instead of manually setting the attribute on the videos, you may insert the Comment directly from the relationship's save method:

//Create a new Tag instance (fill the array with your own database fields)
$tag = new Tag(['name' => 'Foo bar.']);

//Find the video to insert into a tag
$video = Video::find(1);

//In the tag relationship, save a new video
$tag->videos()->save($video);
Madigan answered 22/3, 2017 at 11:22 Comment(5)
If it's not work, edit your post and explain your relationship for usCheng
Thank you. That fixed it. I was so close.Walt
@João Mantovani Seems you can help me. Look at this : #49513456Montano
@JoãoMantovani how it is possible that u have videos() relation on the tag() model if tag() is the polymorphic model with taggable() morphTo()?Invent
Instead of $tag->videos()->save($videos) do $video->tags()->save($tag) because the video model has many tags and setup morphTo in your video model.Judi
I
23

you missed a step in the associate method, use this:

$tag->videos()->associate($video)->save();
Implied answered 20/1, 2020 at 7:28 Comment(1)
Only this one works for meSox
P
1

You can also try this which worked for me (morphMany):

$rel_data = ['assigned_type'=>'User','assigned_id'=>$user_model->getKey()];

$event->assigned_models()->create($rel_data);
Panpsychist answered 14/6, 2021 at 14:54 Comment(0)
S
0

And if you want to save multi tags you can use code below

route:

Route::post('posts/{id}/tags', 'PostController@storeTags');

your request sends tags as array contains ids

+ Request (application/json) or (form-data)
        {
            "tags": [
              1,2,3,4
            ]
        }

in your controller:

public function storeTags(Request $request, $id)
{
    foreach ($request->tags as $id)
        $tags[] = Tag::find($id);

    $post= Post::find($id);
    $post->tags()->saveMany($tags);

}

and for update:

// sync() works with existing models' ids. [here means: $request->tags]
$post->tags()->sync([1,2,3]); // detaches all previous relations
$post->tags()->sync([1,2,3], false); // does not detach previous relations,attaches new ones skipping existing ids
Subtile answered 10/3, 2020 at 21:20 Comment(0)
D
0

I use this code:

$post->comments->attach($comment);
Drooff answered 23/1, 2021 at 20:17 Comment(0)
R
0

Comment.php

class Comment extends Model
{
use HasFactory;
protected $fillable = ['body','comment_id','comment_type'];
public function commentable()
{
    return $this->morphTo();
}
}

MainController.php

 public function addPost(){
    //add Post
    //Create a new Tag instance (fill the array with your own database fields)
    $post = new Post(['post_name' => 'something post ']);
    
    //Find the comment to insert into a post
    $comment =  Comment::find(1);

    //In the comment relationship, save a new post
    $post->save();
    return ("Post Added");
    }

web.php

Route::get('/add-post',[MainController::class,'addPost']);

https://laravel.com/docs/5.4/eloquent-relationships#inserting-and-updating-related-models

Rogelioroger answered 9/9, 2021 at 6:5 Comment(0)
J
0
$post = Post::create([
  'title' => 'test title',
  'description' => 'test description',
  'status' => 1,
  ]);

$post->comment()->create([ 'body' => "test body",'user_id' => 1]);
Jillayne answered 11/3, 2022 at 12:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.