This guide will help you port your application to ExpressionEngine. If you don’t know, ExpressionEngine is a CMS built on CodeIgniter. Being built on CI makes it easy to write Web Apps using pure CodeIgniter framework, and then port it to EE with few changes.
To start off, you need to create an EE module. The module consists of the following structure:
- module_name
- language
- english
- lang.module_name.php
- english
- models
- mcp.module_name.php
- mod.module_name.php
- upd.module_name.php
- language
Inside lang.module_name.php:
<?php $lang = array( "events_module_name" => 'Your module name here', "events_module_description" => 'A description to your module', ); ?>
Inside mcp.module_name.php
<?php class Events_mcp { function __construct() { $this->EE =& get_instance(); } } ?>
Inside upd.module_name.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class ModuleName_upd { var $version = '1.0'; function __construct() { // Make a local reference to the ExpressionEngine super object $this->EE =& get_instance(); } function install() { $this->EE->load->dbforge(); $data = array( 'module_name' => 'ModuleName' , 'module_version' => $this->version, 'has_cp_backend' => 'n', 'has_publish_fields' => 'y' ); $this->EE->db->insert('modules', $data); } function uninstall() { return TRUE; } function update($current = '') { return FALSE; } }
And finally inside mod.module_name.php:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class ModuleName { function __construct() { // Make a local reference to the ExpressionEngine super object $this->EE =& get_instance(); }
Now place this folder inside “/expressionengine/third_party/”. If everything was done correctly your module should appear in EE’s module manager.
This is the first step in porting your existing CI application to EE. Next step is to put your actual code in the correct way. Briefly, the EE module corresponds to oridinary CI files as follows:
- models folder in EE corresponds to models folder in CI
- mod.module_name.php corresponds to a single CI controller
- Views in CI correspond to templates in EE
Models:
There are no required changes to do if you want to use your CI models in EE. Just places them inside your module’s model folder under EE and they’re going to be available for you to load and use.
Controllers:
Your CI controller code should be placed inside mod.module_name.php under EE. The controller code is not a simple copy and paste though to work. The first problem is the “load” function not being accessible from your new controller file (well since it’s not a normal CI controller). To have access to this function and others as usual, you’ll have to get instance of the CI object which would expose these functions for you to use. So the constructor should look like the following:
mod.module_name.php:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class ModuleName { function __construct() { // Make a local reference to the ExpressionEngine super object $this->EE =& get_instance(); } } ?>
Now replace every call to $this->load() with $this->EE->load(). Same goes for loaded models and libraries. For example:
function addpost() { $this->EE->load->helper('url'); $this->EE->load->helper('form'); $this->EE->load->library('form_validation'); $this->EE->form_validation ->set_rules('post_title', 'Post Title', 'required|max_length[100]|trim|xss_clean'); }
At the end of each function you will not load a view. This is because we will be dealing with EE’s templates which works pretty much differently than a normal View.
In CodeIgniter, usually at the end of the function you’d call a view and pass some data to be rendered by that view. In EE however, templates and controllers work differently. Instead of calling a controller function which loads a view, you call an EE template which calls zero or more functions from the EE controller file (mod.module_name.php). The template also expects the data to be returned in a specific format that you’ll be forced to change your functions returned values to match that format. I’ll use an example of a Blog module for more clarification
Assume we want fetch all posts and comments from the database and display them in a template. Normally in CI controller functions we would it in a single function, and pass it to the view to handle. But given the way templates in EE work where you directly call as much controller functions as you want from it, we have the following options:
- Either break up the function into two, posts in one function and comments in other, each will be solely called from the template.
- Have both posts and their comments placed in one array, which is returned to the template upon the controller function call.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class ModuleName { function __construct() { // Make a local reference to the ExpressionEngine super object $this->EE =& get_instance(); } function get_posts() { $this->EE->load->model('post'); $this->EE->post->db->order_by('post_id', 'asc'); $output_data = $this->EE->post->db->get('posts')->result(); return $this->format_output($output_data); } function get_comments() { $post_id = $this->EE->TMPL->fetch_param('post_id'); $this->EE->load->model('comment'); $output_data = $this->EE->comment->db->get_where('post_id',$post_id)->result(); return $this->format_output($output_data); } } ?>
Notice that the way we’re fetching posts and comments from the database is the normal CI way. The main different things here is the first and last lines in get_comments function and their similarities in get_posts. We’ll talk about the format_output function first.
As I previously mentioned, EE templates expects the function output to be formatted in a specific way. Normally you have only to call
return $this->EE->TMPL->parse_variables($this->EE->TMPL->tagdata, $output_data);
However, this only works given that $output_data is a multidimensional associative array. If you are fetching data from database this way, then you’ll have to convert them to associative arrays since they are returned in form of an array of objects (should be an array of arrays) before passing it to parse_variables function. With quick dirty work I wrote a simple function that takes care of this, for 2 levels deep at most:
function format_output($objects) { //prepares the data to be be used by templates //2 LEVEL PARSING ONLY! $values = array(); foreach($objects as $o) { $vars = get_object_vars($o); $tmp = array(); foreach($vars as $v=>$val) { if(gettype($o->$v) == 'object') { $subvars = get_object_vars($o->$v); $subtmp = array(); foreach($subvars as $subv=>$subval) { $keyname = $subv=="id"?$v."_id":$subv; $subtmp[$keyname]=$o->$v->$subv; } $tmp[$v]=array(0=>$subtmp); } else $tmp[$v]=$o->$v; } $values[]=$tmp; } $output = $this->EE->TMPL->parse_variables($this->EE->TMPL->tagdata, $values); return $output; }
EE Template
Now create a new template that would display blog posts and their comments:
{exp:posts:get_posts} <h2>{post_title}:</h2> <p>{post_body}</p> <h3>Comments:</h3> {exp:posts:get_comments post_id={post_id}} <p id="{comment_id}">{comment_content}</p> {/exp:posts:get_comments} {/exp:posts:get_posts}
For more information about EE modules check out this Module Tutorial on EE’s userguide.