Home Arrow Icon Knowledge base Arrow Icon Global Arrow Icon Can you provide an example of using morphToMany in a Laravel application


Can you provide an example of using morphToMany in a Laravel application


Certainly! In Laravel, the `morphToMany` relationship is used to define a polymorphic many-to-many relationship. This allows a model to belong to more than one other model on a single association.

What is `morphToMany`?

`morphToMany` lets you create a many-to-many polymorphic relationship. This means a model can be associated with multiple other models, and those other models can be of different types.

Common Use Case Example

Imagine you have a tagging system where multiple models like `Post` and `Video` can be tagged with multiple `Tag` models. Both `Post` and `Video` share the ability to be tagged, but they are different models.

Example Scenario

- Models: `Post`, `Video`, `Tag`
- Relationship: Both `Post` and `Video` can have many `Tag`s, and a `Tag` can belong to many `Post`s or `Video`s.

Step-by-Step Example Using `morphToMany`

1. Define Models

Post Model

php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    public function tags()
    {
        return $this->morphToMany(Tag::class, 'taggable');
    }
}

Video Model

php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Video extends Model
{
    public function tags()
    {
        return $this->morphToMany(Tag::class, 'taggable');
    }
}

Tag Model

php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Tag extends Model
{
    public function posts()
    {
        return $this->morphedByMany(Post::class, 'taggable');
    }

    public function videos()
    {
        return $this->morphedByMany(Video::class, 'taggable');
    }
}

2. Database Structure (Conceptual, no tables)

- You have `posts` table and `videos` table.
- You have a `tags` table.
- You create a pivot table called `taggables` with these columns:
- `tag_id` (foreign key to `tags`)
- `taggable_id` (ID of the related model, either post or video)
- `taggable_type` (class name of the related model, e.g., `App\Models\Post` or `App\Models\Video`)

3. Usage Example

php
// Create a post and a video
$post = Post::create(['title' => 'My First Post']);
$video = Video::create(['title' => 'My First Video']);

// Create some tags
$tag1 = Tag::create(['name' => 'Laravel']);
$tag2 = Tag::create(['name' => 'PHP']);

// Attach tags to post
$post->tags()->attach($tag1->id);
$post->tags()->attach($tag2->id);

// Attach tags to video
$video->tags()->attach($tag1->id);

// Retrieve tags for post
$postTags = $post->tags; // Collection of Tag models

// Retrieve posts tagged with 'Laravel'
$laravelTag = Tag::where('name', 'Laravel')->first();
$postsTaggedLaravel = $laravelTag->posts; // Collection of Post models
$videosTaggedLaravel = $laravelTag->videos; // Collection of Video models

Summary

- Use `morphToMany` on the model that owns the tags (e.g., `Post` and `Video`).
- Use `morphedByMany` on the `Tag` model to get the inverse relationship.
- The pivot table stores `tag_id`, `taggable_id`, and `taggable_type`.
- This pattern allows you to flexibly associate tags with multiple different models.

If you want, I can also provide migration examples or more advanced usage tips!