Laravel Get All Morphs for a Many To Many Polymorphic Relationship
As of Laravel version 7, if you are doing Many to Many (Polymorphic) relations with Laravel via the docs here. That will give the ability to fetch $video->tags
and $post->tags
as well as the inverse which would be $tag->videos
and $tag->posts
. But what if you wanted to grab all videos and posts $tag->videosAndPosts
?
Pivot Model Structure
To achieve this, you can create an intermediate Model Pivot table that will allow you to return all morphs from a tag.
1$ artisan make:model -p Taggable
This will create a Pivot Model called Taggable. We are going to overwrite the table name to match that of the pivot, as well as create a method to match that of the morph name for simplicity.
1<?php 2 3namespace App; 4 5use Illuminate\Database\Eloquent\Relations\Pivot; 6 7class Taggable extends Pivot 8{ 9 protected $table = 'taggables';10 11 public function taggable()12 {13 return $this->morphTo();14 }15}
Model Structure
Now we need to create the mapping from our Tag Model.
1namespace App; 2 3use Illuminate\Database\Eloquent\Model; 4 5class Tag extends Model 6{ 7 /** 8 * Get all of the videos/posts that are assigned this tag. 9 */10 public function videosAndPosts()11 {12 return $this->hasMany(Taggable::class);13 }14}
Returning results
We can now return all videos and posts
1$tag = App\Tag::find(1);23foreach ($tag->videosAndPosts as $videoOrPost) {4 //5}
We can also use with()
to minimize queries
1$tag = App\Tag::with('videosAndPosts.taggable')->find(1);23foreach ($tag->videosAndPosts as $videoOrPost) {4 //5}