Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save JoshuaDoshua/bdc4c0f6b81af964a31db9ed43118dad to your computer and use it in GitHub Desktop.
Save JoshuaDoshua/bdc4c0f6b81af964a31db9ed43118dad to your computer and use it in GitHub Desktop.

This creates creates a morphPivot that does the relationship work to allow us to pull the related models from the morphTo model. Using groupby keeps the DB queries as efficient as possible

NOTE: the dual use of Taggable for the trait and the morphPivot might be confusing, consider using App\Models\TaggableMorph as the actual pivot model name.

Models:

App\Models\Tag;
App\Models\Taggable;
App\Concerns\Taggable as TaggableMorph;
App\Models\AnyTaggableModel; // any model that can be tagged

Usage

AnyTaggableModel::first()->related_models;
<?php
namespace App\Concerns;
use App\Models\Tag;
use App\Models\Taggable as TaggableMorph;
trait Taggable
{
/**
* Get all of the tags for the Model.
*
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
*/
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable')
->using(TaggableMorph::class);
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Concerns\Taggable;
class AnyTaggableModel extends Model
{
use HasFactory;
use Taggable;
...
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Tag extends Model
{
use HasFactory;
/**
* The relations to eager load on every query.
*
* @var array
*/
protected $with = [
'taggables.related',
];
/**
* Get the Taggables for the Model.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function taggables()
{
return $this->hasMany(Taggable::class);
}
/**
* Get the related_models attribute.
*
* @return string
*/
public function getRelatedModelsAttribute()
{
return $this->taggables->groupBy('taggable_type');
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\MorphPivot;
class Taggable extends MorphPivot
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = "taggables";
/**
* Get the Tag that owns the Taggable.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function tag()
{
return $this->belongsTo(Tag::class);
}
/**
* Get all of the owning related models.
*
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
*/
public function related()
{
return $this->morphTo(__FUNCTION__, 'taggable_type', 'taggable_id');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment