Skip to content
World Wide Web Server edited this page Jul 4, 2012 · 36 revisions

[color=red][b]Current version: 1.6, 2010-08-25, by WanWizard[/b][/color]

[b]Introduction:[/b]

Modular extensions for CodeIgniter have been around for quite some time: Modular Extensions, HMVC, Matchbox and Modular Separation.

While designing an application framework based on CodeIgniter, I needed a much more flexible system than what is on offer by the extensions mentioned above.

A module in my definition is a complete CodeIgniter mini-application. It needed to support all elements you have in a regular application folder: controllers, models, views, libraries and helpers. All these elements must be loadable using the CodeIgniter standard, automatic, and with a minimum of configuration. And this includes controllers loading other controllers, and models loading other models, to support true HMVC. At the same time, the solution needs to support modulair routing. Not with a fixed format (for example the first URI segment has to be the module name), but using regular CI routing. Also, I wanted as little impact on a standard CodeIgniter installation, as every extension of a core library method might break some CodeIgniter functionality in the future.

[b]Features:[/b]

  • Location of your modules is configurable
  • Supports routing to a module controller
  • Supports cross module calls, also to controller methods
  • Uses standard CodeIgniter routing, no Router library modifications
  • Introduces $this->load->module() via a Loader library extension
  • Support for the default index() method and the _remap() method when routing
  • Supports loading models without CI object assignment, to support ORM libraries
  • Supports module controller return values for true HMVC (as suggested by
  • Allow loading of modules from alternate locations (p.e if you have a modules and a themes directory with a module structure)
  • Allows loading your application folder as a module, so you can call these controllers too [color=red]Supports both version 1.7.2 and 2.0[/color], [b]and requires PHP5+[/b] [url=http://codeigniter.com/forums/member/87583/]n0xie[/url])

[b]Solution:[/b]

By default, Modular CI expends modules to be installed in the directory 'modules', in the same directory as your index.php. If you alter the location, you have to inform the loader that there is a different location. You do that via [code]// set the location of our modules $this->load->module_path( 'modules' );[/code]

If you have modules in multiple locations, all you have to to is you alter the location by calling the module_path() method again, with the new location.

Once the path is set, you can initialize a module by using: [code]// Make the "my_module" module available $this->load->module('my_module');[/code]

If you have long and complex module names, or if your module name is variable (for example because it is user defined), you can load the module with an alternative object name. This decouples the name of the module as it exists on disk from the objectname used in your code: [code]// Make the "my_module_with_a_long_name" module available as 'my_module' $this->load->module('my_module_with_a_long_name', 'my_module');[/code]

Or load a module from a specific location: [code]// Make the "user_selected_theme" theme module available as 'theme' $this->load->module('user_selected_theme', 'theme', APPPATH.'themes');[/code]

You can even load the application folder itself as a module, so you can load controllers in your application folder as module controllers: [code]// Load the application folder as $this->core module $this->load->module('application', 'core', FCPATH);[/code]

[i]A module remembers to location it is loaded from. After initializing it, you can change the module path without affecting the access to the modules methods.[/i]

This is all you have to do. From this moment on, all files from this module can be accessed in a way similar to the way you would normally load them. Note that you don't have to load a library or a module before using it. It will be autoloaded as soon as you reference it: [code]// call a method in a library of our module $this->my_module->library->testlib->func('varA', 'varB');

// call a method in a model of our module $this->my_module->model->testmodel->func('var1', 'var2');

// call a method in a controller of our module $this->my_module->controller->testcntrlr->func('varX', 'varY', 'varZ');

// load a view from our module $this->my_module->view('test');

// load a helper from our module $this->my_module->helper('test');

// and see if it works testhelper();[/code]

[b]Using models in an ORM environment:[/b]

If you are using an ORM solution, you can't use the traditional CodeIgniter way of loading models. Most ORM solutions provide an autoload feature so you could use: [code]// load the datamapper User model $user = new User();[/code]

As the datamapper libraries aren't aware that your models should now be loaded from module model directories, this method can no longer be used. Modular CI provides you with the following solution to load ORM models: [code]// load the datamapper User model $user = $this->my_module->model->User();[/code]

[b]Controllers in HMVC:[/b]

Modular CI also supports controller return values, so you can use it in a true HMVC environment. To use this functionality, simply use: [code]// call a method in a controller of our module, and get the return value $result = $this->my_module->controller->testcntrlr->func('varX', 'varY', 'varZ'); [/code]

[b]Library configuration:[/b]

Modular CI supports the standard CodeIgniter way of configuring a module library. Just create a file with the same name as the library in the modules 'config' directory, as documented in the CodeIgniter user guide.

You can also configure the library at runtime, by passing a config array to the library when you load it: [code]// define a custom configuration $config = array('var1' => 'value1', 'var2' => 'value2');

// load the my_module library testlib with our custom config $this->my_module->library->testlib( $config ); [/code]

[b]Routing:[/b]

Unlike other solutions, Modular CI doesn't use extensions of the Router library to allow routing to module controllers.

Instead, it uses a 'Modulerouter' controller, that utilizes the fact that controllers can call module controllers, to route to the requested module controller.

This solution has several benefits:

  • No modifications to the Router library
  • All CodeIgniter routing features are available to alter URI's
  • the Modulerouter has full access to the $CI superobject
  • You can use the Modulerouter constructor for authentication/autorisation tasks

Since the Modulerouter is a normal controller, you can name it whatever you want.

How does routing work? Very simple, just like any other route your would use. If your application is fully modular, and you like the straitforward way of the other solutions by starting your URI with the module name, you can use: [code]// you can choose to route all your standard application controllers first // and everything else to the module router $route['(welcome|test)(.)'] = '$1$2'; // welcome.php and test.php are application controllers $route['(.)'] = 'modulerouter/$1'; // everything is assumed to be a module[/code]

You can route on a per-module basis, using: [code]// only do module routing for this module $route['example/(.*)'] = 'modulerouter/example/$1';[/code]

Or do something more complicated, like: [code]// your URI doesn't have to start with a module name // only do module routing for this module $route['site/(:any)/(.*)'] = 'modulerouter/$1/$2';

// your module URI can be constructed from different URI parts // use different segments to route to the module $route['(:any)/controller/(.*)'] = 'modulerouter/$1/$2';[/code]

[b]Download:[/b]

Modular CI is available on [url=http://bitbucket.org/wanwizard/modular-ci/]BitBucket[/url]. Click on the 'get source' button to download the code, or clone the repository using Mercurial.

[b]Discuss:[/b]

See this [url=http://codeigniter.com/forums/viewthread/164350/]forum thread[/url].

[color=red][b]Developed by WanWizard[/b][/color]

Clone this wiki locally