Laravel All About Polymorphic Relationships
Hello Artisans, in this tutorial I'll show you polymorphic relationships in Laravel. From today's tutorial, we can understand how we can create many-to-many relationship as well as we can also know the different methods which are related to polymorphic relationships like attach, detach, sync, saveMany, create or get all records etc. Suppose we've the following table schema:
posts
id - integer
name - string
videos
id - integer
name - string
tags
id - integer
name - string
taggables
tag_id - integer
taggable_id - integer
taggable_type - string
Here posts and videos all the table share the same single table of unique tags.
Next, we're ready to define the relationships on the models. The Post
and Video
models will both contain a tags
method that calls the morphToMany
method provided by the base Eloquent model class.
The morphToMany
method accepts the name of the related model as well as the "relationship name". Here we'll refer to the relationship as "taggable". As in the intermediate table we use taggable_id and taggable_type. So, try to use same name of relationship method and prefix of the column name.
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable');
}
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable');
}
Now we define the inverse relationship in Tag.php for it's possible parent models.
public function posts()
{
return $this->morphedByMany(Post::class, 'taggable');
}
public function videos()
{
return $this->morphedByMany(Video::class, 'taggable');
}
Now we can call our relationship from our model classes.
Retrieve the Records
If we want to retrieve all the tags of a Post/Video we can do that by following
use App\Models\Post;
use App\Models\Video;
//for post
$post = Post::find(1);
foreach ($post->tags as $tag) {
//
}
//for video
$video = Video::find(1);
foreach ($video->tags as $tag) {
//
}
We can also find the posts and videos of a specific tag like below
use App\Models\Tag;
//for post
$tag = Tag::find(1);
foreach ($tag->posts as $post) {
//
}
//for video
foreach ($tag->videos as $video) {
//
}
Save Records
If we want to save tags for a specific post/video, we can do the following
use App\Models\Post;
use App\Models\Video;
$post = Post::find(1);
$tag = new Tag;
$tag->name = "Laravel";
//for posts
$post->tags()->save($tag);
//for videos
$video = Video::find(1);
$video->tags()->save($tag);
We can also save many tags at once using saveMany().
use App\Models\Post;
use App\Models\Video;
$post = Post::find(1);
$tag1 = new Tag;
$tag->name = "Laravel";
$tag2 = new Tag;
$tag->name = "VueJs";
//for posts
$post->tags()->saveMany([$tag1,$tag2]);
//for videos
$video = Video::find(1);
$video->tags()->saveMany([$tag1,$tag2]);
Or we can also save via attach() method
use App\Models\Post;
use App\Models\Video;
$post = Post::find(1);
$tag1 = Tag::find(1);
$tag2 = Tag::find(2);
//for posts
$post->tags()->attach([$tag1->id,$tag2->id]);
//for videos
$video = Video::find(1);
$video->tags()->attach([$tag1->id,$tag2->id]);
Delete Records
We can also delete single/multiple records using detach() method.
use App\Models\Post;
use App\Models\Video;
$post = Post::find(1);
$tag1 = Tag::find(1);
$tag2 = Tag::find(2);
//for posts
$post->tags()->detach([$tag1->id,$tag2->id]);
//for videos
$video = Video::find(1);
$video->tags()->detach([$tag1->id,$tag2->id]);
Or we wan use sync() which will attach if data is not exist and detach if data is already exists.
use App\Models\Post;
use App\Models\Video;
$post = Post::find(1);
$tag1 = Tag::find(1);
$tag2 = Tag::find(2);
//for posts
$post->tags()->sync([$tag1->id,$tag2->id]);
//for videos
$video = Video::find(1);
$video->tags()->sync([$tag1->id,$tag2->id]);
That's it for today. Hope you'll enjoy through this tutorial. Thanks for reading. ๐