How to filter User by role based on the called Model?

748 views Asked by At

I'm using Laratrust to manage these roles:

  • Patient
  • Doctor

I've a class called User which is the main entity, then I have a specific class for each role: Patient and Doctor.

Problem

To retrieve a list of users with the role of doctor I have to write:

User::whereRoleIs('doctor')->get();

The problem's that I have defined some relationship within the class Doctor, eg:

<?php

namespace App\Models;

use App\Models\Boilerplate\User;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class Doctor extends User
{
    use HasFactory;

    protected $table = 'users';

    public function patients()
    {
        return $this->belongsToMany(Patient::class, 'invites', 'doctor_id', 'user_id');
    }
}

and I cannot access to the relationship patients from the User model. Is there a way to call Doctor:with('patients')->get() and return automatically the users which have the role of Doctor?

So if I type: Doctor:all() the result must be equal to User::whereRoleIs('doctor')->get()

How can I do this?

1

There are 1 answers

2
Remco Speekenbrink On BEST ANSWER

Splitting data like this by model isn't really the intended use for models. Models in Laravel contain data on a per-table basis. In order to achieve what you want I would either make a DocterService that has methods in it to retrieve docter users by calling User::whereRoleIs('doctor') or just use this method straight away.

If you really want to use the model though you can use scopes. (https://laravel.com/docs/9.x/eloquent#query-scopes) Create a new scope that includes the whereRoleIs('doctor') method

<?php
 
namespace App\Scopes;
 
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
 
class DoctorScope implements Scope
{
    /**
     * Apply the scope to a given Eloquent query builder.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
    public function apply(Builder $builder, Model $model)
    {
        $builder->whereRoleIs('doctor');
    }
}

and apply it to the model by adding the following to the model:

    /**
     * The "booted" method of the model.
     *
     * @return void
     */
    protected static function booted()
    {
        static::addGlobalScope(new DoctorScope);
    }