nevadskiy/laravel-many-to-morph

The missing polymorphic relationship for Eloquent.

0.2.0 2024-04-02 18:17 UTC

This package is auto-updated.

Last update: 2024-11-02 19:25:14 UTC


README

A package that simplifies and enhances Many-To-Many polymorphic relationships in Laravel's Eloquent ORM.

Stand With Ukraine

PHPUnit Code Coverage Latest Stable Version License

📚 Introduction

One common type of relationship in Laravel's Eloquent ORM is the Many-To-Many polymorphic relation. While it works well for most use cases, you might encounter certain challenges that require more elegant solutions, for example:

  1. When you have numerous related models, you need to define a separate relation for each type of model.
  2. It is hard to retrieve all related models at once.

This package introduces a new Many-To-Morph relationship, inspired by the Directus's Many-to-Any relation that handles these problems.

📝 Table of Contents

🔌 Installation

Install the package via Composer:

composer require nevadskiy/laravel-many-to-morph

📄 Documentation

Configuring Relationship

To configure this relationship, you need to use the HasManyToMorph trait, which provides a manyToMorph method for defining the relation as follows:

use Nevadskiy\ManyToMorph\HasManyToMorph;
use Nevadskiy\ManyToMorph\ManyToMorph;

class Tag extends Model
{
    use HasManyToMorph;

    public function taggables(): ManyToMorph
    {
        return $this->manyToMorph('taggable');
    }
}

Retrieving Relationships

You can retrieve relationships as shown below:

use App\Models\Tag;
use App\Models\Post;
use App\Models\Video;

$tag = Tag::find(1);

foreach ($tag->taggables as $taggable) {
    if ($taggable instanceof Post) {
        // ...
    } else if ($taggable instanceof Video) {
        // ...
    }
}

Ordering Relationships

To order relationships, you can use the orderBy method directly on the taggables relation like so:

use App\Models\Tag;

$tag = Tag::find(1);

$tag->taggables()->orderBy('position')->get();

Eager Loading Relationships

Eager loading relationships can be done like this:

use App\Models\Tag;
use App\Models\Post;
use App\Models\Video;

$tags = Tag::query()
    ->with(['taggables' => function (ManyToMorph $taggables) {
        $taggables->morphWith([
            Post::class => ['media'],
            Video::class => ['previews'],
        ]);
    }])
    ->get();

Attaching Relationships

You can attach relationships with the following code:

use App\Models\Tag;
use App\Models\Post;
use App\Models\Video;

$tag = Tag::find(1);

$post = Post::find(1);

$tag->taggables()->attach($post);

$video = Video::find(1);

You can also attach a model with pivot attributes:

$tag->taggables()->attach($video, ['score' => 1337]);

Detaching Relationships

To detach relationships, use the following code:

use App\Models\Tag;
use App\Models\Video;

$tag = Tag::find(1);

$video = Video::find(1);

$tag->taggables()->detach($video);

📜 License

This package is open-source and is released under the MIT License. Please refer to the LICENSE file for more information.