Emanuel
Emanuel

Reputation: 17

Laravel Complex Relationships Through Polymorphism

I have the following models using Laravel 5.3:

Provider:

// Provider model

$primaryKey = 'id'

public function activities()
{
    return $this->hasMany(Activity::class);
}

Activity:

// Activity model

$primaryKey = 'id'

public function provider()
{
    return $this-belongsTo(Provider::class);
}

public function semesters()
{
    return $this->hasMany(Semester::class);
}

public function semesterPurchases()
{
    return $this->hasManyThrough(Purchase::class, Semester::class, 'activity_id', 'purchasable_id')
        ->where('purchasable_type', Semester::class);
}

Semester:

// Semester model

$primaryKey = 'id'

public function activity()
{
    return $this->belongsTo(\App\Models\Activity::class, 'activity_id', 'id');
}

Purchase:

// Purchase model

$primaryKey = 'id'

public function purchasable()
{
    return $this->morphTo();
}

In my case Semester::class is the purchasable_type. Is there a way to establish a relationship between Provider::class and Purchase::class? In order to make it possible to do something like this:

$providers = Provider::select('id', 'name', 'address')
  ->with('purchases')
  ->where('providers.id', 1)
  ->get();

I would prefer not to go through activities like so:

$providers = Provider::select('id', 'name', 'address')
  ->with('activities.purchases')
  ->where('providers.id', 1)
  ->get();

which I know I can do using hasManyThrough on the Activity::class

Upvotes: 0

Views: 67

Answers (1)

Jonas Staudenmeir
Jonas Staudenmeir

Reputation: 25906

Laravel has no native support for a direct relationship.

I've created a package for cases like this: https://github.com/staudenmeir/eloquent-has-many-deep

class Provider extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function purchases()
    {
        return $this->hasManyDeep(
            Purchase::class,
            [Activity::class, Semester::class],
            [null, null, ['purchasable_type', 'purchasable_id']]
        );
    }
}

Provider::find($id)->purchases;

Upvotes: 1

Related Questions