c-griffin
c-griffin

Reputation: 3026

Laravel - Dynamic relationship using hasManyThough() and unique merge

I can think of several ad-hoc ways to do this, but I'm really looking for a 'best practices' type of solution.

I have 3 tables involved
- users (user_id)
- usages ('user_id', 'provider_id', 'nurse_id', 'patient_id')
- usage_alerts ('usage_id')

Im trying to eager load alerts using hasManyThrough() based on a user's role.

The user_id field is agnostic, and can apply to any role, so merging and filtering needs to take place.

Using $this->hasManyThrough('UsageAlert', 'Usage')->get() will return a collection, making the ->merge() method available. However, when eager loading, on return, i get an error since it's a collection object.

Call to undefined method Illuminate\Database\Eloquent\Collection::addEagerConstraints()

For example, this is my current relation (returns the error above)

public function alerts() 
{ 

    $alerts = $this->hasManyThrough('UsageAlert', 'Usage')->get();

    if(Sentry::getUser()->inGroup(Sentry::findGroupByName('provider')))
        $alerts->merge($this->hasManyThrough('UsageAlert', 'Usage', 'provider_id'));

    if(Sentry::getUser()->inGroup(Sentry::findGroupByName('patient')))
        $alerts->merge($this->hasManyThrough('UsageAlert', 'Usage', 'patient_id'));

    if(Sentry::getUser()->inGroup(Sentry::findGroupByName('nurse')))
        $alerts->merge($this->hasManyThrough('UsageAlert', 'Usage', 'nurse_id'));

    return $alerts;

}

Any suggestions?
Pperhaps too much complexity for a relationship?

Upvotes: 2

Views: 2048

Answers (1)

bishop
bishop

Reputation: 39434

Best practice manipulates the relationship, though official documentation on how lacks. For your scenario, you can union the additional queries into the primary "agnostic" relationship:

$relation = $this->hasManyThrough('UsageAlert', 'Usage');

foreach (['provider','patient','nurse'] as $group) {
    if (Sentry::getUser()->inGroup(Sentry::findGroupByName($group))) {
        $relation->getBaseQuery()->union(
            $this->
            hasManyThrough('UsageAlert', 'Usage', $group . '_id')->
            getBaseQuery()->
            select('UsageAlert.*') // limits union to common needed columns
        );
    }
}

return $relation;

This approach returns a Relation, rather than a Collection, as would be expected by API users.

Upvotes: 5

Related Questions