Объединение таблиц в ORM - PullRequest
       5

Объединение таблиц в ORM

0 голосов
/ 26 декабря 2011

Я пытаюсь написать свой собственный модуль RBAC на Kohana. Я не хочу использовать существующий модуль, я просто хочу научиться этому.

Моими таблицами являются: пользователи, роли, разрешения и users_roles, role_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 разрешение на запись сообщения?

Спасибо за вашу помощь!

Ответы [ 3 ]

1 голос
/ 28 декабря 2011

Один запрос, но только два объединения по сравнению с предыдущим ответом

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();
}

}

0 голосов
/ 07 января 2012

Вот лучшее решение, которое будет выполнять более быстрый запрос, если указан первичный ключ или экземпляр модели:

<?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');
    }

    // ...
}
0 голосов
/ 26 декабря 2011

Я нашел решение, в 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 имеет разрешение на запись .

Isесть более простое решение?

...