Я - большой фанат CodeIgniter, но хотя, этот фреймворк очень хорош собой даже "из коробки", до начала разработки приложения на нем, я всегда добавляю в него несколько библиотек. Одна из них - класс для работы с ACL. Раньше я использовал в своих проектах простой класс, написанный мною, но не так давно решил перейти на довольно функциональный класс из фреймворка Zend (и встроить его в CodeIgniter, само собой). И теперь хочу поделиться этим опытом с моими читателями.
Скачайте последнюю версию Zend framework
Создайте папку Zend в /system/application/libraries.
Скопируйте Acl, Acl.php и Exception.php из фреймворка в нее
Создайте файл Zacl.php в папке libraries и скопируйте в него приведенный ниже код.
Добавьте 'zacl' в массив $autoload['libraries'] в /system/application/config/autoload.php.
Содержимое файла Zacl.php
<?php if (!defined('BASEPATH')) exit('No direct script access allowed'); class Zacl { var $CI; function __construct() { $this->CI =& get_instance(); set_include_path(get_include_path() . PATH_SEPARATOR . BASEPATH . "application/libraries"); require_once(APPPATH . '/libraries/Zend/Acl.php'); require_once(APPPATH . '/libraries/Zend/Acl/Role.php'); require_once(APPPATH . '/libraries/Zend/Acl/Resource.php'); $this->acl = new Zend_Acl(); $this->acl->addRole(new Zend_Acl_Role('default')); $query = $this->CI->db->get('tbl_aclresources'); foreach($query->result() AS $row){ $this->acl->add(new Zend_Acl_Resource($row->resource)); if($row->default_value == 'true'){ $this->acl->allow('default', $row->resource); } } $this->CI->db->order_by("roleorder", "ASC"); $query = $this->CI->db->get('tbl_aclroles'); foreach($query->result() AS $row){ $role = (string)$row->name; $this->acl->addRole(new Zend_Acl_Role($role), 'default'); $this->CI->db->from('tbl_acl'); $this->CI->db->join('tbl_aclresources', 'tbl_acl.resource_id = tbl_aclresources.id'); $this->CI->db->where('type', 'role'); $this->CI->db->where('type_id', $row->id); $subquery = $this->CI->db->get(); foreach($subquery->result() AS $subrow){ if($subrow->action == "allow"){ $this->acl->allow($role, $subrow->resource); } else { $this->acl->deny($role, $subrow->resource); } } $this->CI->db->from('tbl_users'); $this->CI->db->where('roleid', $row->id); $userquery = $this->CI->db->get(); foreach($userquery->result() AS $userrow){ $this->acl->addRole(new Zend_Acl_Role($userrow->user), $role); $this->CI->db->from('tbl_acl'); $this->CI->db->join('tbl_aclresources', 'tbl_acl.resource_id = tbl_aclresources.id'); $this->CI->db->where('type', 'user'); $this->CI->db->where('type_id', $userrow->userid); $usersubquery = $this->CI->db->get(); foreach($usersubquery->result() AS $usersubrow){ if($usersubrow->action == "allow"){ $this->acl->allow($userrow->user, $usersubrow->resource); } else { $this->acl->deny($userrow->user, $usersubrow->resource); } } } } } // проверка имеет ли роль доступ к ресурсу function check_acl($resource, $role = '') { if (!$this->acl->has($resource)) { return 1; } if (empty($role)) { if (isset($this->CI->session->userdata['user'])) { $role = $this->CI->session->userdata['user']; } } if (empty($role)) { return false; } return $this->acl->isAllowed($role, $resource); } }
Теперь вы очень легко можете проверить наличие доступа к ресурсу:
// проверка доступа к ресурсу 'dummy' залогиненым пользователем if ($this->zacl->check_acl('dummy')){ ... } // проверка доступа к ресурсу 'manage_users' роли 'admin' if ($this->zacl->check_acl('manage_users', 'admin')) { ... }
Думаю код вполне понятный, но на всякий случай я прикладываю еще и структуру таблиц.
CREATE TABLE IF NOT EXISTS `tbl_acl` ( `id` int(11) NOT NULL AUTO_INCREMENT, `type` enum('role','user') NOT NULL, `type_id` int(11) NOT NULL, `resource_id` int(11) NOT NULL, `action` enum('allow','deny') NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT; CREATE TABLE IF NOT EXISTS `tbl_aclresources` ( `id` int(11) NOT NULL AUTO_INCREMENT, `resource` varchar(255) NOT NULL, `description` longtext NOT NULL, `aclgroup` varchar(255) NOT NULL, `aclgrouporder` int(11) NOT NULL, `default_value` enum('true','false') NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT; CREATE TABLE IF NOT EXISTS `tbl_aclroles` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `roleorder` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT; INSERT INTO `tbl_aclroles` (`id`, `name`, `roleorder`) VALUES (1, 'Admin', 1), (2, 'User', 2), (3, 'Guest', 3); CREATE TABLE IF NOT EXISTS `tbl_users` ( `userid` int(11) NOT NULL AUTO_INCREMENT, `user` longtext NOT NULL, `pass` longtext NOT NULL, `firstname` longtext NOT NULL, `prefix` longtext NOT NULL, `lastname` longtext NOT NULL, `gender` enum('m','f') NOT NULL, `roleid` int(11) NOT NULL, `mail` longtext NOT NULL, PRIMARY KEY (`userid`) ) ENGINE=MyISAM DEFAULT;
Отредактировав свои контроллеры, настроив права доступа и изменив модель авторизации, вы получите превосходную заготовку для создания нового приложения на CodeIgniter


Спасибо большое!
Спасибо большое за разъяснение.
Если Вы большой фанат CI наверняка уже присматривались к Fuelphp ? Понравился ли он?
@Денис, нет, не присматривался. зато потихоньку перехожу на Symfony2. В целом хочу уходить от CI, всё меньше и меньше он мне нравиться
Надеюсь, Вы созреете и напишите отзыв - субъективный взгляд при переходе на Симфони с CI
Рано или поздно многие начинают писать сложные проекты и ломают голову на что перейти.