CodeIgniter: Theming, A Common Problem

I recently was on stackoverflow.com and ran across an interesting question by a fellow tasked to produce a “project” under any stack he wanted. He chose to use a LAMP Stack with CodeIgniter at the core. In his question it seemed that he might have been confused about how to use the view. This is something I have seen before, both in confusion and misuse. I have always felt like there was a hole in the explanation of views on the issue of Theming.

Theming is kind of intrinsic to any website. Most sites have a common layout they maintain around their content, in ASP.Net we use master pages, and most of us who’ve developed under LAMP have done something akin to theming at one point. Where I feel the breakdown comes from is the MVC push of code igniter. In POPC (Plain old PHP Code) we were very used to this, in the simplest form it looked something like this:

My Site

Copyright © 2011 - My Name

We’ve all seen this type of php before, it’s old and most of us probably don’t do it anymore. The problem comes from the MVC paradigm that code igniter thrusts onto us (note: this is not a bad thing). The way we display things in CodeIgniter is to load views, the default behaviour is to render the output straight to the screen. What this does is focuses the view around a single view call:

$this->load->view("ViewForThisAction", array("stuff"=>"the","view"=>"needs"));

This is from my understanding primarily due to the method of GZipping the output employed by the framework, but what if we need a more complex view? And also, what if we need to wrap this all with a common theme? The answer: Pre-Render in parts.

In CodeIgniter, you can render a view to a variable, this is a very useful option, because it allows us to render the view in parts, and assemble it later.

$bodyContent = $this->load->view("ViewForThisAction", array("stuff"=>"it-needs"), true);
$this->load->view("MasterTheme", array("bodyContent" => $bodyContent);

Now from here this opens up lots of possibilities. Common controls, Database driven menus, etc can all be loaded ahead of time effectively “in parallel” with the main page content pipeline before going to the master theme for rendering.

Theme Class

class Theme
{
	private $CI;

	public __construct()
	{
		parent::__construct();
		
		$this->CI =& get_instance();
	}
	
	private function RenderMenu()
	{
		$menuItems = array("Home", "News", "Forums");
		
		return $this->CI->load->view("Theme/Menu", $menuItems, true);
	}
	
	public function Render($bodyContent)
	{
		$data = array(
			"menu" => $this->RenderMenu(),
			"body" => $bodyContent
		);
		
		$this->load->view("Theme/Master", $data);
	}
}

Usage

$this->load->libary('theme');
$viewOutput = $this->load->view("WhateverActionView", array(...), true);
$this->theme->Render($viewOutput);

Theme

My Fancy Site


What this allows us to do is to focus on what’s in the content of the page, not the site. The theme class handles all that common load stuff that’s in every page, and the controller doesn’t need to know about it, or deal with it. Your controller’s responsibility is more refined and your code becomes simpler.

Additionally you can also have the Theme class just generate the data for the common blocks, and pass that along to the master theme, where a subsequent

load->view("Theme/Menu", $menu); ?>

Could be used in place of dumping html blobs, either way works just as well as the other so it’s really up to the implementer.