【问题标题】:Joining tables in ORMORM中的连接表
【发布时间】:2011-12-26 13:57:24
【问题描述】:

我正在尝试在 Kohana 中编写自己的 RBAC 模块。 我不想使用现有的模块,我只是想这样做来学习。

我的表是:用户、角色、权限和users_roles、roles_permissions(因为用户角色和角色权限之间的多对多关系);

我的用户模型:

class Model_User extends ORM {

    protected $_primary_key = 'user_id';

    protected $_has_many = array(
        'roles' => array(
            'model'   => 'role',
            'through' => 'users_roles',
        ),
    );
}

我的榜样:

class Model_Role extends ORM {

    protected $_primary_key = 'role_id';

    protected $_has_many = array(
        'users' => array(
            'model'   => 'user',
            'through' => 'users_roles',
        ),

        'permissions' => array(
            'model'   => 'permission',
            'through' => 'roles_permissions',
        ),
    );
}

和我的权限模型:

class Model_Permission extends ORM {

    protected $_primary_key = 'permission_id';

    protected $_has_many = array(
        'roles' => array(
            'model'   => 'role',
            'through' => 'roles_permissions',
        ),
    );
}

我创建用户:

$user = ORM::factory('user');
$user->username = 'johndoe';
$user->email = 'john@doe.com';
//etc
$user.save();

我创建角色:

$author = ORM::factory('role');
$author->name = 'author';
$author->save();

我创建权限:

$read = ORM::factory('permission');
$read->name = 'read';
$read->description = 'can read posts';
$read->save();

$write = ORM::factory('permission');
$write->name = 'write';
$write->description = 'can write posts';
$write->save();

我为用户添加角色:

$user->add('roles', $author);

我为角色添加权限:

$author->add('permissions', $read);
$author->add('permissions', $write);

一切正常。

但是,我的问题是如何检查用户是否具有给定的权限:在这种情况下如何检查 johndoe 是否有权限 write em> 一个帖子?

感谢您的帮助!

【问题讨论】:

  • 获取所有作者权限,然后遍历它们,看看写权限是否在该组权限对象中。
  • 我想检查 $user 是否有写权限,而不是 $author 是否有写权限..
  • 那么你首先需要获取用户的角色,然后通过他们查看是否授予权限。这有什么复杂的?
  • 没错,但没有更优雅的解决方案。我不能在单个查询中执行此操作吗?
  • 您正在使用 ORM。据我了解,当您使用 ORM 提供的接口时,您不应该关心查询。当您想自己编写 ORM 时,ORM 会按照您的要求进行操作。由于您不想使用现成的解决方案(通常强烈建议使用这种解决方案,因为 ORM 是复杂的软件),所以请使用现有的解决方案。如果您对如何自己创建复杂的 ORM 感兴趣,那么有很多书籍对事物进行了详细描述。但正如所写,这个主题很复杂,所以在开始编写代码之前要阅读几千页。

标签: php mysql orm kohana


【解决方案1】:

一个查询,但与上一个答案相比只有两个连接

class Model_User extends ORM {

// ... some stuff here

public function has_permission($permission_name)
{
    return (bool) ORM::factory('permission')
        ->where('permission.name', '=', $permission_name)
        ->join('roles_permissions')
            ->on('roles_permissions.permission_id', '=', 'permision.permission_id')
        ->join('roles_users')
            ->on('roles_users.role_id', '=', 'roles_permissions.role_id')
            ->on('roles_users.user_id', '=', DB::expr((int) $this->user_id))
        ->count_all();
}

}

【讨论】:

    【解决方案2】:

    我在 1 个查询中找到了解决方案:

    $count = ORM::factory('permission')
                                ->join('roles_permissions')
                                ->on('permission.permission_id', '=', 'roles_permissions.permission_id')
                                ->join('roles')
                                ->on('roles.role_id', '=', 'roles_permissions.role_id')
                                ->join('users_roles')
                                ->on('roles.role_id', '=', 'users_roles.role_id')
                                ->join('users')
                                ->on('users.user_id', '=', 'users_roles.user_id')
                                ->on('users.user_id', '=', DB::expr($user->user_id))
    ->where('permission.name', '=', 'write')
                                ->find_all()
                                ->count();
    

    如果是$count > 0,则表示$user有写权限

    有没有更简单的解决方案?

    【讨论】:

      【解决方案3】:

      这是一个更好的解决方案,当提供主键或模型实例时,它会执行更快的查询:

      <?php
      
      class Model_User extends ORM {
      
          // ...
      
          /**
           * Check if a user is allowed to perform an action based on permissions
           * attached to the user's roles.
           *
           * @param  int|string|Model_Permission $permission name, primary key or instance of permission
           * @return boolean TRUE if allowed; FALSE otherwise
           */
          public function is_allowed_to($permission)
          {
              // We have a permission name
              if (is_string($permission) AND ! is_numeric($permission))
                  return (bool) ORM::factory('permission')
                      ->where('permission.name', '=', $permission)
                      ->join('roles_permissions')
                          ->on('roles_permissions.permission_id', '=', 'permission.permission_id')
                      ->join('roles_users')
                          ->on('roles_users.role_id', '=', 'roles_permissions.role_id')
                      ->where('roles_users.user_id', '=', $this->pk())
                      ->count_all();
      
              // We can get the permission primary key
              // to perform a faster query
              $permission_id = ($permission instanceof Model_Permission)
                  ? $permission->pk()
                  : $permission;
      
              return (bool) DB::select(array(DB::expr('COUNT(*)'), 'records_found'))
                  ->from('roles_permissions')
                  ->join('roles_users')
                      ->on('roles_users.role_id', '=', 'roles_permissions.role_id')
                  ->where('roles_permissions.permission_id', '=', $permission_id)
                  ->where('roles_users.user_id', '=', $this->pk())
                  ->execute()
                  ->get('records_found');
          }
      
          // ...
      }
      

      【讨论】:

        猜你喜欢
        • 2016-07-15
        • 1970-01-01
        • 1970-01-01
        • 2018-08-07
        • 2023-01-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多