-
Notifications
You must be signed in to change notification settings - Fork 0
modular seperation
This is a solution for people that are looking for a way to keep associated models, views and controllers in the same directory and thereby making their application more modular.
[h3]Installaion[/h3]
It uses two extended core classes; [b]MY_Loader[/b] and [b]MY_Router[/b], both of which should be placed in your [b]application/libraries/[/b] folder.
You will also need to create the [b]application/modules/[/b] folder.
[b]application/libraries/MY_Loader.php[/b] [code]<?php if (!defined('BASEPATH')) { exit('No direct script access allowed'); }
class MY_Loader extends CI_Loader { function model($model, $name = '', $db_conn = FALSE) { $module = ''; $CI = &get_instance();
if (is_dir(APPPATH . 'modules/' . $CI->uri->segment(1))) {
$module = $CI->uri->segment(1);
}
if (is_dir(APPPATH . 'modules/' . $CI->uri->segment(2) . '/controllers/' . $CI->uri->segment(1))) {
$module = $CI->uri->segment(2);
}
if (file_exists(APPPATH . 'modules/' . $module . '/models/' . $model . EXT)) {
$model = '../modules/' . $module . '/models/' . $model;
}
parent::model($model, $name, $db_conn);
}
function view($view, $vars = array(), $return = FALSE)
{
$module = '';
$CI = &get_instance();
if (is_dir(APPPATH . 'modules/' . $CI->uri->segment(1))) {
$module = $CI->uri->segment(1);
}
if (is_dir(APPPATH . 'modules/' . $CI->uri->segment(2) . '/controllers/' . $CI->uri->segment(1))) {
$module = $CI->uri->segment(2);
}
if (file_exists(APPPATH . 'modules/' . $module . '/views/' . $view . EXT)) {
$view = '../modules/' . $module . '/views/' . $view;
}
parent::view($view, $vars, $return);
}
} ?>[/code]
[b]application/libraries/MY_Router.php[/b] [code]<?php if (!defined('BASEPATH')) { exit('No direct script access allowed'); }
class MY_Router extends CI_Router { function _set_route_mapping() { if ($this->config->item('enable_query_strings') === true && isset($_GET[$this->config->item('controller_trigger')])) { $this->set_class($_GET[$this->config->item('controller_trigger')]);
if (isset($_GET[$this->config->item('function_trigger')])) {
$this->set_method($_GET[$this->config->item('function_trigger')]);
}
return;
}
@include(APPPATH . 'config/routes' . EXT);
$this->routes = (!isset($route) || !is_array($route)) ? array() : $route;
unset($route);
$this->default_controller = (!isset($this->routes['default_controller']) || $this->routes['default_controller'] == '') ? false : strtolower($this->routes['default_controller']);
$this->uri_string = $this->_get_uri_string();
if ($this->uri_string == '/') {
$this->uri_string = '';
}
if ($this->uri_string == '') {
if ($this->default_controller === false) {
show_error("Unable to determine what should be displayed. A default route has not been specified in the routing file.");
}
// Is the default_controller an accelerant?
if (is_dir(APPPATH . 'modules/' . $this->default_controller)) {
$this->set_directory('../modules/' . $this->default_controller . '/controllers/');
}
$this->set_class($this->default_controller);
$this->set_method('index');
log_message('debug', "No URI present. Default controller set.");
return;
}
unset($this->routes['default_controller']);
if ($this->config->item('url_suffix') != "") {
$this->uri_string = preg_replace("|" . preg_quote($this->config->item('url_suffix')) . "$|", "", $this->uri_string);
}
foreach (explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->uri_string)) as $val) {
$val = trim($this->_filter_uri($val));
if ($val != '') {
$this->segments[] = $val;
}
}
$this->_parse_routes();
$this->_reindex_segments();
}
function _validate_segments($segments)
{
// Is the requested controller an accelerant but not the default accelerant controller?
if (count($segments) > 1 && file_exists(APPPATH . 'modules/' . $segments[0] . '/controllers/' . $segments[1] . EXT)) {
$this->set_directory('../modules/' . $segments[0] . '/controllers');
$segments = array_slice($segments, 1);
return $segments;
}
// Is the requested controller an default accelerant controller?
if (file_exists(APPPATH . 'modules/' . $segments[0] . '/controllers/' . $segments[0] . EXT)) {
$this->set_directory('../modules/' . $segments[0] . '/controllers');
return $segments;
}
// Is the requested controller an accelerant but not the default accelerant controller in a sub-folder?
if (count($segments) > 2 && file_exists(APPPATH . 'modules/' . $segments[1] . '/controllers/' . $segments[0] . '/' . $segments[2] . EXT)) {
$this->set_directory('../modules/' . $segments[1] . '/controllers/' . $segments[0]);
$segments = array_slice($segments, 2);
return $segments;
}
// Is the requested controller an default accelerant controller in a sub-folder?
if (count($segments) > 1 && file_exists(APPPATH . 'modules/' . $segments[1] . '/controllers/' . $segments[0] . '/' . $segments[1] . EXT)) {
$this->set_directory('../modules/' . $segments[1] . '/controllers/' . $segments[0]);
$segments = array_slice($segments, 1);
return $segments;
}
parent::_validate_segments($segments);
}
} ?>[/code]
[h3]How to use[/h3] A module consists of at least one controller and might include a number of models and/or views. These must be placed in the [b]application/modules/MODULENAME/[/b] folder (with [b]MODULENAME[/b] being the name of your module, ie. blog, forum, etc).
The files must be placed in the following folders:
[b]/system/application/modules/MODULENAME/models/ /system/application/modules/MODULENAME/views/ /system/application/modules/MODULENAME/controllers/[/b]
Your controllers will then be accessible as [b]www.example.com/MODULENAME/CONTROLLER/METHOD[/b].
Consider this URI:
[b]www.example.com/blog/entries/view/[/b]
In the above example, CI will open the [b]application/modules/blog/controllers/entries.php[/b] controller and call the [b]view[/b] method within it.
However, an URI like this:
[b]www.example.com/blog/[/b]
Will only look for the controller with the same name as the module, ie. [b]application/modules/blog/controllers/blog.php[/b] controller and call the [b]index[/b] method.
In order to let you call methods from your default controller (the one with the same name as your module, application/modules/blog/controllers/blog.php), CI will in fact handle this URI:
[b]www.example.com/blog/entries/view/[/b]
By first looking for a method called entries in [b]application/modules/blog/controllers/blog.php[/b] and then for a [b]application/modules/blog/controllers/entries.php[/b] and call its [b]view[/b] method.
You can even put controllers in sub-folders. If you do, the same rules apply as above, except the URI will need to have the FOLDERNAME before your MODULENAME:
[b]www.example.com/FOLDERNAME/MODULENAME/METHOD/[/b] (if default controllers has the called METHOD)
or
[b]www.example.com/FOLDERNAME/MODULENAME/CONTROLLER/METHOD/[/b]
[h3]Important note for PHP4 users[/h3] Because of a bug, if you are using PHP4, CI does not extend the loader class. Until Rick fixes this, you can do it yourself by editing the [b]Base4.php[/b] file like this:
[b]system/codeigniter/Base4.php[/b] [code]... class CI_Base extends MY_Loader { ...[/code] That is, replacing CI_Loader with MY_Loader.