如何在laravel 5中建立用户和角色关系?

时间:2015-08-30 15:04:32

标签: laravel laravel-5 eloquent

我有两张桌子:

User ->
 id : 
 name : 
 role_id : ->refernces('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

        ];

我收到错误:

Trying to get property of non-object

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

4 个答案:

答案 0 :(得分:6)

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

用户表

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。

如果您有任何进一步的相关问题,请与我们联系。或者如果您需要完整实施,我会提供给您。

答案 1 :(得分:4)

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

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

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

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

$user->role->name;

答案 2 :(得分:1)

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

$user->role->role_name

它取代role列而不是关系。

答案 3 :(得分:0)

我注意到你没有使用laravel默认表命名约定, 您正在使用user_roles wherelas laravel命名约定您应该使用的状态: role_user(按字母顺序和单数形式)

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

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

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