获取特定角色的所有用户从另一个Laravel模型中

huangapple go评论61阅读模式
英文:

How to get all Users with a specific Role from another Model in Laravel

问题

我有一个用户模型,有3个角色(['student', 'admin', 'teacher']),使用spatie/laravel-permission。我想要创建一个像Student、Admin、Teacher这样的模型,它将只返回具有这些角色的用户。例如,我想要创建一个Student模型,只返回具有学生角色的所有用户。

我应该如何实现这个目标?

我创建了一个Student模型,并且使用了protected $table='users',但我不知道如何让它只返回具有学生角色的用户。

英文:

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

答案1

得分: 1

以下是翻译好的内容:

我不确定是否可以使用Laravel原生的方式来实现这一点,而且这不是一个好的实践,因为这种方法不可扩展。想象一下将来出于某种原因,您需要向应用程序添加另一个角色,然后您必须创建另一个模型并执行相同的操作,如果继续这样下去,您将面临大量的模型,它们都在做相同的事情。
Model 的理念是代表表的数据结构。
我建议使用关系和服务类而不是这种方法,这更加清晰。



namespace App\Services;

use Spatie\Permission\Models\Role;

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

您可以在应用程序的任何地方注入这个类,然后简单地调用 execute() 方法并获取数据。

英文:

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 App\Services;

use Spatie\Permission\Models\Role;

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

答案2

得分: 0

So, you have a User model, like this:

class User extends Model {
    //...
}

Now, let's create a static property, like this:

protected static $mainRole = '';

You can override Laravel methods, as shown in this example: https://stackoverflow.com/questions/54891635/laravel-eloquent-override-get-method-when-using-where. This is a method taken from the example:

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

You will need to customize it differently based on your needs. To infer the calling model's $mainRole in the get method and use this override in your User model, you may need to override more methods and add supportive fields or functions for your query builder. This approach is similar to what you did in CakePHP, where you override methods in the base classes.

If your User can differentiate when $mainRole is true or not (defaulting to the "normal" approach when there's no value for $mainRole), you can create subclasses like this:

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

These subclasses override $mainRole with the desired value for Admin and inherit the $mainRole logic from User, allowing you to create multiple submodels this way.

英文:

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: https://stackoverflow.com/questions/54891635/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 App\Override;
class QueryBuilder extends \Illuminate\Database\Query\Builder {
    //@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.

huangapple
  • 本文由 发表于 2023年5月13日 19:14:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76242427.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定