I am trying to limit access to a particular model to only certain user groups. However, within those groups, there are certain prohibited services. I am trying to set up a global scope that will block the prohibited services.
The code I have (not working) is this.
protected static function boot()
{
parent::boot();
static::addGlobalScope('status', function (Builder $builder) {
$builder->whereHas('groups.users', fn($q) => $q->where('user_id', Auth::user()->id))
->whereDoesntHave('groups.prohibitedServiceTypes', fn($q) => $q->where('service_type_id', $this->service_type_id));
});
}
The reason it doesn't work is that $this
is not available for the global scope.
For some clarification, the model here is called encounter
. An Encounter can have many groups, and a group can have many users. A group also has many prohibited service types. I want to select those records where the service_type_id
is not in the current group's list of prohibitions.
In SQL, I'd write this:
SELECT * FROM encounters e
JOIN group_encounter ge ON (e.id = ge.encounter_id)
JOIN groups g ON (g.id=ge.group_id)
JOIN group_user gu ON (gu.group_id=g.id)
WHERE gu.user_id = <current user> AND NOT EXISTS
(SELECT * FROM group_prohibited_service_types WHERE service_type_id = <current service type>)
But I'm trying to do this the laravel way.
I am trying to limit access to a particular model to only certain user groups. However, within those groups, there are certain prohibited services. I am trying to set up a global scope that will block the prohibited services.
The code I have (not working) is this.
protected static function boot()
{
parent::boot();
static::addGlobalScope('status', function (Builder $builder) {
$builder->whereHas('groups.users', fn($q) => $q->where('user_id', Auth::user()->id))
->whereDoesntHave('groups.prohibitedServiceTypes', fn($q) => $q->where('service_type_id', $this->service_type_id));
});
}
The reason it doesn't work is that $this
is not available for the global scope.
For some clarification, the model here is called encounter
. An Encounter can have many groups, and a group can have many users. A group also has many prohibited service types. I want to select those records where the service_type_id
is not in the current group's list of prohibitions.
In SQL, I'd write this:
SELECT * FROM encounters e
JOIN group_encounter ge ON (e.id = ge.encounter_id)
JOIN groups g ON (g.id=ge.group_id)
JOIN group_user gu ON (gu.group_id=g.id)
WHERE gu.user_id = <current user> AND NOT EXISTS
(SELECT * FROM group_prohibited_service_types WHERE service_type_id = <current service type>)
But I'm trying to do this the laravel way.
Share Improve this question asked Mar 5 at 19:50 mankowitzmankowitz 2,0531 gold badge19 silver badges43 bronze badges1 Answer
Reset to default 1you can use whereColumn to compare two columns within your query:
protected static function boot()
{
parent::boot();
static::addGlobalScope('status', function (Builder $builder) {
$builder->whereHas('groups.users', fn($q) => $q->where('user_id', Auth::user()->id))
->whereDoesntHave('groups.prohibitedServiceTypes', fn($q) =>
$q->whereColumn('group_prohibited_service_types.service_type_id', 'encounters.service_type_id')
);
});
}
however you should note that Auth::user()
should NOT be used in scopes or models, since it would return null for any context outside your Http\Controllers