【问题标题】:How to make user, and roles relationship in Laravel 5如何在 Laravel 5 中建立用户和角色关系
【发布时间】:2015-11-24 16:51:37
【问题描述】:

我有两张桌子:

User ->
  id : 
  name : 
  role_id : ->references('id')->on('roles');

Roles ->
  id :
  role_name :
  access :

我正在尝试访问用户的角色详细信息。

我的用户模型有:

public function role()
{
    return $this->belongsTo('App\Role');
}

我的榜样有:

public function user()
{
    return $this->hasMany('App\User');
}

当我尝试执行以下操作时:

$user = User::find(1);

$details = [
    'name' => $user->first_name,
    'role' => $user->role->role_name
];

我得到错误:

试图获取非对象的属性

我的角色表包含​​访问列,其中包含对不同路由的权限数组。所以我的用户将只有一个角色。而一个角色可以有多个用户。

怎么做?

【问题讨论】:

    标签: laravel laravel-5 eloquent


    【解决方案1】:

    在我最近的项目中,我以这种方式处理了这些需求。 首先是数据库表结构/迁移

    用户表

    class CreateUserTable extends Migration {
    
        public function up() {
            Schema::create('user', function (Blueprint $table) {
                $table->increments('id');
                $table->string('name');
                $table->string('email')->unique();
                $table->string('password', 60);
                $table->boolean('status')->default(0);
                $table->boolean('is_admin')->default(0);
                $table->boolean('notify')->default(0);
                $table->rememberToken();
                $table->timestamps();
            });
        }
    
        public function down() {
            Schema::drop('user');
        }
    
    }
    

    角色表

    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Database\Migrations\Migration;
    
    class CreateRoleTable extends Migration {
        public function up()
        {
            Schema::create('role', function (Blueprint $table) {
                $table->increments('id');
                $table->string('name')->unique();
                $table->string('display_name')->nullable();
                $table->string('description')->nullable();
                $table->boolean('status')->default(0);
                $table->timestamps();
            });
        }
    
        public function down()
        {
            Schema::drop('role');
        }
    
    }
    

    角色与用户关系表

    class CreateRoleUserTable extends Migration {
        public function up() {
            // Create table for associating roles to users (Many-to-Many)
            Schema::create('role_user', function (Blueprint $table) {
                $table->integer('user_id')->unsigned();
                $table->integer('role_id')->unsigned();
    
                $table->foreign('user_id')->references('id')->on('user')
                    ->onUpdate('cascade')->onDelete('cascade');
                $table->foreign('role_id')->references('id')->on('role')
                    ->onUpdate('cascade')->onDelete('cascade');
    
                $table->primary(['user_id', 'role_id']);
            });
        }
    
        public function down() {
            Schema::drop('role_user');
        }
    
    }
    

    在这些表之后,您必须通过分配给特定角色来处理权限。

    权限

    class Permission extends Migration {
    
        public function up() {
            Schema::create('permission', function (Blueprint $table) {
                $table->increments('id');
                $table->string('name')->unique();
                $table->string('pattern');
                $table->string('target');
                $table->string('module');
                $table->string('display_name')->nullable();
                $table->boolean('status')->default(0);
                $table->timestamps();
            });
        }
    
        public function down() {
            Schema::drop('permission');
        }
    
    }
    

    权限和角色表关系

    class PermissionRole extends Migration {
        public function up() {
            // Create table for associating roles to permission (Many-to-Many)
            Schema::create('permission_role', function (Blueprint $table) {
                $table->integer('permission_id')->unsigned();
                $table->integer('role_id')->unsigned();
    
                $table->foreign('permission_id')->references('id')->on('permission')
                    ->onUpdate('cascade')->onDelete('cascade');
                $table->foreign('role_id')->references('id')->on('role')
                    ->onUpdate('cascade')->onDelete('cascade');
    
                $table->primary(['permission_id', 'role_id']);
            });
        }
    
        public function down() {
            Schema::drop('permission_role');
        }
    
    }
    

    最后我们的模型看起来很像:

    用户模型

    namespace App;
    
    use Illuminate\Auth\Authenticatable;
    use Illuminate\Database\Eloquent\Model;
    use Illuminate\Auth\Passwords\CanResetPassword;
    use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
    use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
    
    class User extends Model implements AuthenticatableContract, CanResetPasswordContract {
    
        use Authenticatable, CanResetPassword;
        protected $table = 'user';
        protected $fillable = ['name', 'email', 'password', 'is_admin'];
        protected $hidden = ['password', 'remember_token'];
    
        public function scopeActive($query) {
            return $query->whereStatus('1');
        }
        public function scopeAdmin($query) {
            return $query->whereIsAdmin('1');
        }
        public function scopeNotify($query) {
            return $query->whereNotify('1');
        }
    
        public function roles() {
            return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');
        }
    
        public function attachRole($role) {
            if (is_object($role)) {
                $role = $role->getKey();
            }
            if (is_array($role)) {
                $role = $role['id'];
            }
            $this->roles()->attach($role);
        }
    
        public function detachRole($role) {
            if (is_object($role)) {
                $role = $role->getKey();
            }
            if (is_array($role)) {
                $role = $role['id'];
            }
            $this->roles()->detach($role);
        }
    
        public function attachRoles($roles) {
            foreach ($roles as $role) {
                $this->attachRole($role);
            }
        }
    
        public function detachRoles($roles) {
            foreach ($roles as $role) {
                $this->detachRole($role);
            }
        }
    
        public function isSuperUser() {
            return (bool)$this->is_admin;
        }
    
        public function hasAccess($permissions, $all = true) {
            if ($this->isSuperUser()) {
                return true;
            }
            return $this->hasPermission($permissions, $all);
        }
    
        public function hasPermission($permissions) {
            $mergedPermissions = $this->getMergedPermissions();
            //dd($mergedPermissions);
            if (!is_array($permissions)) {
                $permissions = (array)$permissions;
            }
    
            foreach ($permissions as $permission) {
                $matched = false;
                // We will set a flag now for whether this permission was
                // matched at all.
                $founded_perms = find_in($mergedPermissions, "name", $permission);
                if (!empty($founded_perms)) {
                    $matched = true;
                }
    
            }
    
            if ($matched === false) {
                return false;
            }
    
            return true;
        }
    
        public function getMergedPermissions() {
            $permissions = array();
            foreach ($this->getRoles() as $group) {
                $permissions = array_merge($permissions, $group->permissions()->get()->toArray());
            }
            return $permissions;
        }
    
        public function getRoles() {
            $roles = [];
            if ($this->roles()) {
                $roles = $this->roles()->get();
            }
            return $roles;
        }
    }
    

    角色模型

    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Role extends Model {
        /**
         * The database table used by the model.
         *
         * @var string
         */
        protected $table = 'role';
        /**
         * The attributes that are mass assignable.
         *
         * @var array
         */
        protected $fillable = ['name', 'display_name', 'description'];
    
        public function scopeActive($query) {
            return $query->whereStatus('1');
        }
    
        /**
         * Many-to-Many relations with User.
         *
         * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
         */
        public function users() {
            return $this->belongsToMany('App\User');
        }
    
        public function permissions() {
            return $this->belongsToMany("App\Permission");
        }
    
    }
    

    权限模型

    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Permission extends Model {
        protected $table = 'permission';
        /**
         * The attributes that are mass assignable.
         *
         * @var array
         */
        protected $fillable = ['name', 'pattern', 'target', 'module', 'display_name', 'status'];
    
        public static function displayable() {
            $prepared_array = [];
            $temp = self::orderBy('module')->get()->toArray();
            foreach ($temp as $sin) {
                $prepared_array[$sin['module']][] = $sin;
            }
            return $prepared_array;
        }
        public function scopeActive($query) {
            return $query->whereStatus('1');
        }
    
        public function roles() {
            return $this->belongsToMany("App\Role");
        }
    }
    

    嗯,这就是使用 laravel 5 实现基本 ACL 和 Auth 的基本结构。

    如果您还有其他相关问题,请告诉我。或者,如果您需要完整的实施,我会提供给您。

    【讨论】:

    • @Sadar 你能进一步解释一下吗?那么每个表中的典型值是什么?
    • 您能进一步解释一下吗?那么每个表中的典型值是什么?
    • @Daniel 好吧,user 用于用户相关信息,rolepermission 存储管理、订阅者等角色,权限是您在系统下获得的所有权限的列表,用户拥有角色和角色有很多权限。所以,role_user 用于用户角色关系,permission_role 用于检查每个角色可以访问的内容。
    【解决方案2】:

    我遇到了问题,我在用户表中有一个角色列,所以当我在做的时候

    $user->role->role_name
    

    它正在获取role 列而不是关系。

    【讨论】:

    • 你也可以使用$user->role()->role_name来区分关系和属性。
    • 我正在学习 laravel,这是一个好点。 +1 @HarryGeo
    【解决方案3】:

    我注意到你没有使用 laravel 默认的表命名约定, 您正在使用 user_roles 而 laravel 命名约定说明您应该使用: role_user(字母和单数)

    您可以通过声明自定义表名来覆盖belongsToMany。

    public function users() {
        return $this->belongsToMany('App\User', 'user_roles');
    }
    

    在第二个节点上也有一些很好的库来处理这些事情,看看:https://github.com/romanbican/roles

    【讨论】:

    • 我更新了我的问题,请再看看。我现在正在学习,所以我现在宁愿远离图书馆。
    【解决方案4】:

    对于 one-to-many 关系,您不需要数据透视表,因此您可以删除 user_roles 表。然后将role_id 列添加到您的users 表中,这将为您的roles 表引用id 列。接下来为每个模型定义如下关系:

    // User.php
    public function role()
    {
        return $this->belongsTo('App\Role');
    }
    

    // Role.php
    public function users()
    {
        return $this->hasMany('App\User');
    }
    

    现在您可以通过如下关系访问您的角色:

    $user->role->name;
    

    【讨论】:

    • 它不起作用。我的用户将只有一个角色,那么它是多对多的吗?
    • 我推断你想要多对多,因为你有一个数据透视表,如果你想要一对多关系,这没有用。如果你想要一个一对多的关系,去掉user_roles 表,并在你的用户表中添加一个role_id 列。这将允许您为每个用户指定一个角色。
    • 另外,当您应用我建议的更改时,究竟是什么不起作用?错误信息是什么?
    • 我已更新我的答案以反映您对问题的更改。
    • 感谢您指出,我做了这些更改,但仍然出现同样的错误。
    猜你喜欢
    • 1970-01-01
    • 2017-04-19
    • 2018-08-19
    • 2021-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-23
    • 2019-01-20
    相关资源
    最近更新 更多