skip to Main Content

I have a User Model with 3 roles([‘student’,’admin’,’teacher’]) using spatie/larevel-permission
I want to be able to create a Model like Student, Admin, Teacher, that will return the users with that roles only.
EG.
I want to create a Student Model to only return All users with student role.

so i can perform queries like. Student::get() etc.

Please how can i achieve this?

I created a model Student and i use the protected $table=’users’ but i dont know how to make it return only Users with student roles

2

Answers


  1. I am not sure if this is even possible using Laravel native accent and This is not good practice because this approach is not expandable. Imagine in the future for some reason you need to add another role to your application and you have to create another Model and do the same stuff again and if this continues then you are going to face a lot of Models which they all do the same.
    The idea of Model is to represent data structure of a table.
    I suggest using relations & Service classes instead of this approach which is neat.

    
    
    namespace AppServices;
    
    use SpatiePermissionModelsRole;
    
    class GetAdminsService
    {
        public function execute()
        {
            return Role::query()->where('name', 'administrator')->first()->users;
        }
    }
    
    

    and you can inject this class anywhere in your application and simply call the execute() method and get the data

    Login or Signup to reply.
  2. So, you have a User model, like this:

    class User extends Model {
        //...
    }
    

    Now, let’s create a static property, of the like of

    protected static $mainRole = '';
    

    so far, so good. Now, you can override Laravel methods, like in this example: Laravel – Eloquent override get method when using where. This is a method taken from the example, which is not yet your solution, but it’s a good starting point for your thinking:

    namespace AppOverride;
    class QueryBuilder extends IlluminateDatabaseQueryBuilder {
        //@Override
        public function get($columns = ['*']) {            
            if ($this->from == 'OrderStatus') {
               // customize the call
            } else {
                //Return default
                return parent::get($columns);
            }
        }
    }
    

    Of course, you will need to do it differently and since I do not have a Laravel project in front of me, I will not provide you the exact source-code. However, you will need to somehow infer in this get what the calling model’s $mainRole is and use this override for Builder at your User model. You may need to override further methods in order to achieve this goal and you may need to add some supportive fields or functions for your query builder. I did not do this in Laravel, but I did something very similar in CakePHP and the approach was to see what the base classes are and override some methods in this manner.

    Now, if your User is already able to differentiate between the case when $mainRole is truey or not (defaulting to the "normal" approach when there is no value for $mainRole), you can simply create subclasses of the form of:

    class Admin extends User {
        protected static $mainRole = 'Admin';
    }
    

    which overrides $mainRole with the desired value for Admin and inherits the $mainRole-logic from User. Hence, you can create as many submodels you like this way.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search