Blog header image

Using Many To Many Polymorphic Relations with Laravel Eloquent

Posted on Aug 22nd, 2016

Laravel's documentation shows a great example of using a m2m polymorphic relation. The examples shows how to share tags accross 2 different resources (posts and videos). While working on a side project, I found another similiar use case and just thought to share. This projects is related to disc golf tournaments. One feature of the project allows visitors to quickly search for tournaments and view related information on an event page. This event page will include videos and a list of related courses. In the future, I would love to have a great way for visitors to find course and player information, including videos. Athough it is rare that videos will relate to many tournaments or courses, it is likely they will relate to many players. So ... sounds like a great use for polymorphism. I already have an Event, Course, Player, and Video model with corresponding tables. What I haven't created yet is the polymorphic table. I'll use a similar wording convention as the Laravel doc example. Let's use "videoables" as the table name to host all our resources that can be linked to a video. ```console php artisan make:migration create_videoables --create="videoables" ``` Once the migration file is created I will need to setup the columns. We will need a column for the video Id (video_id), the Id of the resource (videoable_id) and the resource model (videoable_type). I also added a foreign constraint for the video_id. ```php Schema::create('videoables', function (Blueprint $table) { $table->unsignedInteger('video_id'); $table->unsignedInteger('videoable_id'); $table->string('videoable_type'); $table->foreign('video_id')->references('id')->on('videos')->onUpdate('cascade')->onDelete('cascade'); }); ``` Let's migrate. ```console php artisan migrate ``` Next, let's inform our Eloquent models of this new relationship. On the `Event.php`, `Course.php` and `Player` models I add a `videos()` method. ```php public function videos() { return $this->morphToMany(Video::class, 'videoable'); } ``` I'll definitely want the inverse so I can see how many events, players, etc are related to the video resource. So let's at this bit to the `Video.php` model. ```php public function events() { return $this->morphedByMany(Event::class, 'videoable'); } ``` Now let's attach a couple videos to an event model and persist it to the DB. ``` $event->videos()->attach([13, 14]); ``` Done.