A package that simplifies and enhances Many-To-Many polymorphic relationships in Laravel's Eloquent ORM.
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:
- When you have numerous related models, you need to define a separate relation for each type of model.
- 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.
Install the package via Composer:
composer require nevadskiy/laravel-many-to-morph
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');
}
}
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) {
// ...
}
}
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 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();
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]);
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);
This package is open-source and is released under the MIT License. Please refer to the LICENSE file for more information.