CodeIgniterの学習 53 - HMVCモジュールを改造してコントローラ単位(モジュール単位)での使用・不使用制御をconfigファイルで行えるようにする
久しぶりのエントリー。やりたいことは表題の通り。
CodeIgniterのモジュール単位(コントローラ単位)での使用可能・不可能の制御を組み込んで、
環境に応じて使用できるモジュールを変更できるようにする。
用途としては、
- リリース後に一時的に一部機能のみ停止したい。
- ソース構成は同じだが複数の環境にソースを設置し(フロントエンド用・バックエンド用等)、使用できるモジュールを分けたい。(ただし、フロント・バックエンド用でソース構成を分けた方が安全と言えば安全だが)
といった用途。
なお、ユーザー権限毎や、グループ権限毎の制御は組み入れていない。
もう一つ上位レベルでの使用制御。
尚前提として、
http://d.hatena.ne.jp/dix3/20081128/1227802844
http://d.hatena.ne.jp/dix3/20081129/1227964872
http://d.hatena.ne.jp/dix3/20081201/1228113261
http://d.hatena.ne.jp/dix3/20081203/1228237872
が済んでいること。
ソース
改造ソースを貼っておく。いつもながら無保証。HMVCを使ってかつ拡張しようという人は、あまり居ないと思うので、画面は貼らない。
興味のある人だけ試してね。
ソース1新設:application/config/route_active.php
各自の環境によって異なるだろう。
使い方は見れば分かると思うが、apacheの.htaccessみたいな書き方だと思ってください。
正規表現は使えない、あとtasklist/editのみallowとかいう制御は出来ない。
allならば全て許可、または拒否
default_routeは、拒否された時の呼びだし先。指定無しの時はshow_404。
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); //ルートの使用、不使用制御 $active_group = "default"; //$active_group = "develop"; $route_active['default']['order_by'] = array("deny","allow"); $route_active['default']['deny_from'] = array("all"); $route_active['default']['allow_from'] = array("tasklist","flickr","auth"); $route_active['default']['default_route'] = array("flickr"); $route_active['develop']['order_by'] = array("deny","allow"); $route_active['develop']['deny_from'] = array("all"); $route_active['develop']['allow_from'] = array("all"); $route_active['develop']['default_route'] = array(); /* End of file route_active.php */ /* Location: ./application/config/route_active.php */ ?>
こんな感じで、任意のactive_groupを切り替えて使えるようにしてみた。
ソース2:application/libraries/MY_Router.php
HMVCソースを拡張
<?php (defined('BASEPATH')) OR exit('No direct script access allowed'); /* define the modules base path */ define('MODBASE', APPPATH.'modules/'); /* define the offset from application/controllers */ define('MODOFFSET', '../modules/'); /** * Modular Extensions - PHP5 * * Adapted from the CodeIgniter Core Classes * @copyright Copyright (c) 2006, EllisLab, Inc. * @link http://codeigniter.com * * Description: * This library extends the CodeIgniter router class. * * Install this file as application/libraries/MY_Router.php * * @copyright Copyright (c) Wiredesignz 2008-11-20 * @version 5.1.40 * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. **/ // @modify: dix3 // @purpose: モジュール単位(コントローラ単位)での使用可能・不可能制御の組み込み // @link:http://d.hatena.ne.jp/dix3/20081209/1228816805 class MY_Router extends CI_Router { var $default_route = array(); var $redirect_count = 0; public function _validate_request($segments) { if(isset($segments[0]) && preg_match('#^mdl_#iu',$segments[0])){ // /mdl_ から始まるURLはルーティングの対象外とするようにした(URLで直接呼べないように) show_404($this->fetch_directory().$segments[0]); }elseif(isset($segments[0]) && !$this->_route_active_check($segments[0])){ //モジュール単位(コントローラ単位)での使用可能・不可能制御 if($this->default_route && 0===$this->redirect_count){ $this->redirect_count++; return $this->_validate_request($this->default_route); }else{ show_404($this->fetch_directory().$segments[0]); } }else{ //end (isset($segments[1])) OR $segments[1] = NULL; /* locate the module controller */ list($module, $controller) = Router::locate($segments); /* no controller found */ ($module === FALSE) AND show_404($controller); /* set the module directory */ Router::$path = ($controller) ? $module : NULL ; /* set the module path */ $path = ($controller) ? MODOFFSET.$module.'/controllers/' : NULL; $this->set_directory($path); /* remove the directory segment */ if ($controller != $module AND $controller != NULL) $segments = array_slice($segments, 1); return $segments; // /mdl_ から始まるURLはルーティングの対象外とするようにした(URLで直接呼べないように) } //end } //呼び出したコントローラを使うかどうかのチェック function _route_active_check($controller_name) { $ret = false; if(defined('CRON') && CRON ){//バッチ起動時は常にtrue return true; } if(@include(APPPATH.'config/route_active'.EXT)){ $route_active = ( ! isset($route_active) OR ! is_array($route_active)) ? array() : $route_active; $active_group = isset($active_group) ? $active_group : ""; if($active_group){ $order_by = isset($route_active[$active_group]['order_by']) ? $route_active[$active_group]['order_by'] : "deny"; $allow_from = isset($route_active[$active_group]['allow_from']) ? $route_active[$active_group]['allow_from'] : ""; $deny_from = isset($route_active[$active_group]['deny_from']) ? $route_active[$active_group]['deny_from'] : ""; $this->default_route = isset($route_active[$active_group]['default_route']) ? $route_active[$active_group]['default_route'] : ""; foreach((array) $order_by as $v){ foreach((array) ${"{$v}_from"} as $v2){ if("all" === strtolower($v2) || $controller_name === strtolower($v2)){ if($v === "allow"){ $ret = true; } if($v === "deny"){ $ret = false; } } } } } } return $ret; } } class Router { public static $path; /** Locate the controller **/ public static function locate($segments) { list($module, $controller) = $segments; /* a module? */ if ($module AND is_dir(MODBASE.$module)) { ($controller == NULL) AND $controller = $module; /* a module sub-controller? */ if(is_file(MODBASE.$module.'/controllers/'.$controller.EXT)) return array($module, $controller); /* a module controller? */ return array($module, $module); } /* an application controller? */ if (is_file(APPPATH.'controllers/'.$module.EXT)) return array($module, NULL); /* no controller found */ return array(FALSE, NULL); } } /* End of file MY_Router.php */ /* Location: ./application/libraries/MY_Router.php */ ?>
ソースはindex.phpと、configファイル以外同一にして複数環境を設置する一つの方法。
フレームワーク標準で、drupal等のCMSみたいなモジュール管理機構があると本当はいいんだけどね。
今日はここまで。