英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论