Pull to refresh

Codeigniter — облегчаем себе жизнь (расширяем базовый контроллер)

CodeIgniter *
На сегодняшний день, практически в любом приложении необходимо работать с несколькими языками и обеспечивать контроль доступа.
Некоторое время назад я у себя в блоге описывал как работать с этими вещами в codeignier, но блог закрыт а вопросы у некоторых остались всё такие-же.


Для начала подготовим наш приложение:
расширяем роуты:
Открываем routes.php(/system/application/config/routes.php)
добавляем следущие строчки:
$route['(ru|en)'] = $route['default_controller'];
$route['(ru|en)/(.+)'] = "$2";
* This source code was highlighted with Source Code Highlighter.

таким образом теперь мы к любому методу, любого контроллера можем обращятся 3 способами:
www.yourapp/controller/action
www.yourapp/ru/controller/action
www.yourapp/en/controller/action

Создаём также 2 языковых файла interface_lang.php (/system/application/language/english/interface_lang.php и /system/application/language/russian/interface_lang.php)
Приготовления по языку закончены, теперь подготовим наш контроль доступа.

Для контроля доступа я использую Zend_Acl. Очень удобная вещь.
Скачиваем ZendFramework. Создаём папку extensions(system/extensions) и переносим туда папку library/Zend
дальше создаем 2 хелпера:
zend_framework_loader_helper.php (/system/application/helpers/zend_framework_loader_helper.php)
<? php
   if (!defined('BASEPATH')) exit('No direct script access allowed');
   //
   ini_set('include_path', ini_get('include_path').PATH_SEPARATOR.BASEPATH.'extensions/');
   require_once('Zend/Loader.php');

   Zend_Loader::loadClass('Zend_Acl');
   Zend_Loader::loadClass('Zend_Acl_Role');
   Zend_Loader::loadClass('Zend_Acl_Resource');
* This source code was highlighted with Source Code Highlighter.

и zend_framework_acl_helper.php (/system/application/helpers/zend_framework_acl_helper.php)
<? php
   function init_roles() {
      $acl = new Zend_Acl();
      
      //определяем ресурсы/контроллеры
      $acl->add(new Zend_Acl_Resource('login'));
      $acl->add(new Zend_Acl_Resource('welcome'));
      $acl->add(new Zend_Acl_Resource('logout'));

      // определяем роли
      $acl->addRole(new Zend_Acl_Role('guest'));
      $acl->addRole(new Zend_Acl_Role('member'));
      
      //определяем доступ
      $acl->allow('guest','login');
      $acl->deny('guest','welcome');
      $acl->deny('guest','logout');

      $acl->deny('member','login');
      $acl->allow('member','welcome');
      $acl->allow('member','logout');

      return $acl;
}
* This source code was highlighted with Source Code Highlighter.

Здесь я подразумеваю, что у нас небольшое приложение которое состоит из 3 контроллеров и нам необходимо
создать только 2 группы пользователей

Дальше открываем autoload.php(/system/application/config/autoload.php)
и добавляем наши хелперы
$autoload['helper'] = array('zend_framework_loader','zend_framework_acl');
* This source code was highlighted with Source Code Highlighter.

Приготовления закончены теперь надо бы начать всё это использовать,
то есть реализовать проверку этого всего в наших контроллерах

Есть несколько способов как расширить функциональность контроллера:
1. Прописывать небоходимые действия в конструкторе.
2. Делать тоже самое в методе _remap().
3. Расширить класс контроллер и наследовать свои контроллеры уде от него.

Первые два способа хороши когда вам неообходимо добавить уникальные особенности в ваш контроллер, однако если таким образом прописывать вещи одинаковые для всех контроллеров, то код дублируется, что не есть хорошо.
Поэтому будем рассматривать третий способ.

Я буду предпологать, что данные о пользователе(такие как его id, имя, принадлежность к группе) в храните в сессии используя стандартный механихм сессий для codeigniter

Итак начнём:

Создадим файл My_Controller.php (/system/application/libraries/My_Controller.php)
<? php
class MY_Controller extends Controller {
   private $resource = null
   private $priviledge = null;
   // роль пользователя по умолчанию 
   private $default_role = 'guest';
   private $ci;
   private $acl;
   private $language;

   public function MY_Controller(){
      parent::Controller();
      
      // определяем язык
      $lang = $this->uri->segment(1);

      if($lang == 'en'){
         $this->language = $lang;
      }
      else {
         $this->language = 'ru';
      }

      // подгружаем нужный язык
      switch($lang):

         case 'en':
         $this->lang->load('interface', 'english');
         $this->config->set_item('language', 'english');
         break;

         case 'ru':
         $this->lang->load('interface', 'russian');
         $this->config->set_item('language', 'russian');
         break;

         default:
         $this->lang->load('interface', 'russian');
         $this->config->set_item('language', 'russian');
         break;

      endswitch;

      // вызываем init_roles из zend_framework_alc_helper.php
      $this->acl = init_roles();

      // обращаемся к нашему роутеру для определения контроллера и метода
      $router =& load_class('Router');

      // устанавливаем конртоллер в класс и метод в привелегию
      $this->resource  = $router->fetch_class(); 
      $this->priviledge = $router->fetch_method();   
      // просто для удобства что бы не инициализировать позже в приложении
      $this->ci =& get_instance();

      $acl = $this->getACL();

         // если пользователь существует то работаем с его данными
         if($this->session->userdata('userInfo')){
            $identity = $this->session->userdata('userInfo');
            $this->setDefaultRole($identity['user_role']);
         }

      // если пользователь не авторизирован(guest) пытается запросить что-то, то редиректим его на страницу авторизации 
      if(!$acl->isAllowed($this->getDefaultRole(), $this->getResource(), $this->getPriviledge()) && $this->getDefaultRole() == 'guest'){
         redirect('login','refresh');
      }
      // если пользователь авторизирован и пытается запросить что-то куда нет доступа, то редиректим его на страницу авторизации 
      elseif(!$acl->isAllowed($this->getDefaultRole(), $this->getResource(), $this->getPriviledge()) && $this->getDefaultRole() != 'guest'){
         redirect('welcome','refresh');
      }
   }

   // сеттеры и геттеры
   
   public function getInstance(){
      return $this->ci;
   }

   public function getACL(){
      return $this->acl;
   }

   public function getDefaultRole(){
      return $this->default_role;
   }

   public function getPriviledge(){
      return $this->priviledge;
   }
   public function getResource(){
      return $this->resource;
   }

   public function setDefaultRole($role){
      $this->default_role = $role;
   }

   public function getLang(){
      return $this->language;
   }
}
* This source code was highlighted with Source Code Highlighter.

Вот собственно и всё дальше при создании нового контроллера просто заменяем
class Welcome extends Controller{

   public function Welcome(){
      parent:: Controller();
   }
}
* This source code was highlighted with Source Code Highlighter.

на
class Welcome extends MY_Controller{

   public function Welcome(){
      parent:: MY_Controller();
   }
}
* This source code was highlighted with Source Code Highlighter.

и можно работать ))
Tags: codeigniterzend_aclphpframeworks
Hubs: CodeIgniter
Total votes 26: ↑21 and ↓5 +16
Comments 35
Comments Comments 35

Popular right now