7

Just migrated to 4.1 to take advantage of this powerful feature. everything seems to work correctly when retrieving individual 'morphedByXxxx' relations, however when trying to retrieve all models that a particular tag belongs to -- i get an error or no results.

$tag = Tag::find(45); //Tag model name = 'awesome'

//returns an Illuminate\Database\Eloquent\Collection of zero length
$tag->taggable; 

//returns Illuminate\Database\Eloquent\Relations\MorphToMany Builder class
$tag->taggable();

//returns a populated Collection of Video models
$tag->videos()->get();

//returns a populated Collection of Post models
$tag->posts()->get();

My Tag Model class loooks like this:

class Tag extends Eloquent
{
    protected $table = 'tags';
    public $timestamps = true;

    public function taggable()
    {
        //none of these seem to function as expected,
        //both return an instance of MorphToMany

        //return $this->morphedByMany('Tag', 'taggable');
        return $this->morphToMany('Tag', 'taggable');

        //this throws an error about missing argument 1
        //return $this->morphToMany();
    }

    public function posts()
    { 
        return $this->morphedByMany('Post', 'taggable');
    }


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

}

And the Post and Video models look like this:

class Post extends Eloquent
{
    protected $table = 'posts';
    public $timestamps = true;

    public function tags()
    {
        return $this->morphToMany('Tag', 'taggable');
    }

}

I am able to add/remove Tags to Posts and Videos as well as retrieve the related Posts, and Videos for any Tag -- however -- what is the proper way to retrieve all Models having the Tag name 'awesome'?

Antonio Carlos Ribeiro
  • 86,191
  • 22
  • 213
  • 204
zeuben
  • 151
  • 1
  • 8

2 Answers2

6

Was able to figure it out, would love to hear comments on this implementation.

in Tag.php

public function taggable()
{
    return $this->morphToMany('Tag', 'taggable', 'taggables', 'tag_id')->orWhereRaw('taggables.taggable_type IS NOT NULL');
}

in calling code:

$allItemsHavingThisTag = $tag->taggable()
                ->with('videos')
                ->with('posts')
                ->get();
zeuben
  • 151
  • 1
  • 8
0

I just used this on Laravel 5.2 (not sure if it is a good strategy though):

Tag model:

public function related()
{
    return $this->hasMany(Taggable::class, 'tag_id');
}

Taggable model:

public function model()
{
    return $this->belongsTo( $this->taggable_type, 'taggable_id');
}

To retrieve all the inverse relations (all the entities attached to the requested tag):

@foreach ($tag->related as $related)
    {{ $related->model }}
@endforeach

... sadly this technique doesn't offer eager load functionalities and feels like a hack. At least it makes it simple to check the related model class and show the desired model attributes without much fear to look for the right attributes on the right model.

I posted a similar question in this other thread as I am looking for relations not known in advance.

Community
  • 1
  • 1
Federico Stango
  • 548
  • 5
  • 21