How to save in a polymorphic relationship in Laravel?
Stefan Izdrail
Founder & Senior Architect · 2026-06-29
Title: Understanding and Implementing Polymorphic Relationships in Laravel for Saving Records Efficiently
Body: Savvy developers often encounter complex use cases where models can be associated with multiple entities through many-to-many relationships, which can be extended to include polymorphic associations. This blog post aims to explain how to establish and save records with polymorphic relationships in Laravel, ensuring proper data management and efficient storage.
Polymorphic relationships are essential when working with dynamic database models like posts and tags, where the same tag can be associated with multiple types of entities, including Posts, Videos, or other custom models you might create. To achieve this, you must perform operations based on which entity is involved in the relationship at a particular time.
To better understand how to establish polymorphic relationships and save records, let's consider an example:
class Post extends Model
{
/**
* Get all of the tags for the post.
*/
public function tags()
{
return $this->morphToMany('App\Tag', 'taggable');
}
}
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');
}
}
In the example above, we define polymorphic relationships for a Post model associated with tags through a pivot table. Each entity can be assigned to many different tag types: posts, videos, or any other custom models you might create. The 'taggable' key in 'morphedByMany' represents the intermediate table name used to store the pivot relationship and its attributes.
To save records associated with these entities, there are a few possible approaches. Let's look at them:
- Associating a tag to an entity: You can associate a tag with an entity by using either relation 'associate', 'attach', or 'sync'. While 'associate' and 'attach' will set the association without checking if it already exists, 'sync' will update or delete prior associations before establishing the new connection. In this case, you could use:
- Detaching a tag from an entity: To remove the association between a tag and its entities, you can use 'detach' or 'dissociate'. These methods will remove any existing associations without checking if they were first established. You could apply this as:
- Saving a new entity with tags: When saving or updating a new entity, you should make sure to include all existing and updated associations. For example, if you create a video through the 'Video' model, you would add the tag information in the data array before calling the 'save()' method:
- Retrieving entities with their tags: You can also retrieve associated entities and their respective tags using relations. For example, you could get all posts with specific tags by calling:
$tag = Tag::find(1);
$video = Video::find(1);
$tag->videos()->associate($video);
or
$tag->videos()->sync($video);
$tag = Tag::find(1);
$video = Video::find(1);
$tag->videos()->detach($video);
$video = new Video();
// fill the rest of entity properties
$video->tags()->attach([1]); // attach tag id 1
$video->save();
$posts = Post::with('tags')->get(); // return all posts with their assigned tags