CodeIgniter is great framework by its simplicity. But when I moved from CakePHP, I really missed layout pattern. CodeIgniter documentations offer this way to include non-changing site header and footer.

 

 <?php
 $this->load->view('header');
 $this->load->view('template');
 $this->load->view('footer');
 ?>

 

For sure it isn't flexible and does not show page structure in a clear way. For many years I use layout pattern. Layout describes whole page as a template with blocks for header, menu, content, etc like on figure below. On page rendering these blocks are filled with data. I found a small code snipped for CI and improved it. Let's start from simple usage example.

 

Simple Usage of Layout

 

1. Download and put Layout.php into application/libraries folder.

 

2. Create new default layout in views/layout/default.php with content:

 

 <html>
 <head>
 <title>
<?=$title_for_layout?>
</title>
 </head>
 <body>
 <?=$content_for_layout?>
 </body>
 </html>

 

3. Create controller

 

 <?php
 class Main extends CI_Controller {
 // Layout used in this controller
  public $layout_view = 'layout/default';
 public function index() {
 $this->load->library('layout');
 // Load layout library $this->layout->title('Site index page');
 // Set page title $data = array();
 $this->layout->view('index', $data);
 // Render view and layout 
}
 }
 ?>

 

Simple. All data passed to the template in $data is also passed to the layout template.

Handling JS and CSS

This is first area of improvement. I added code to include most used external resources like JavaScript and CSS files. This way it's possible to make optimizations later like stripping/minimizing content or combining into one file.

 

 <?php
 class Main extends CI_Controller {
 public $layout_view = 'layout/default';
 public function index() {
 // Page local resource 
$this->layout->js('js/index.js');
 $this->layout->css('css/index.css');
 $this->layout->title('Page title');
 $this->layout->view('index');
 }
 }
 ?>

 

Use this for layout/default.php to include resources. It contains two variable $css_for_layout and $js_for_layout.

 <html>
 <head>
 <title>
<?=$title_for_layout?>
</title>
 <?=$css_for_layout?>
 <?=$js_for_layout?>
 </head>
 <body>
 <?=$content_for_layout?>
 </body>
 </html>

 

Globalizing CI offers a way to create a parent class for all controllers in the project. It's a very good place to put site global code. For example it is not convenient to specify default template in each controller file since sites usually have only one template. Same is related to resources like JS and CSS, some of them are global and must be included in each site page. Let's create file in application/core/MY_Controller.php with content.

 

 <?php
 class MY_Controller extends CI_Controller {
 // Site global layout
  public $layout_view = 'layout/default';
 function __construct() {
 // Layout library loaded site wide 
$this->load->library('layout');
 // Site global resources 
$this->layout->js('js/jquery.min.js');
 $this->layout->css('css/site.css');
 }
 }
 ?>

 

Next is the controller class itself.

 

 <?php
 class Main extends MY_Controller {
 // Layout is not specified here, it is inherited from MY_Controller function __construct() {
 // Local resource used for all pages served by this controller 
$this->layout->js('js/jlib.min.js');
 $this->layout->css('css/product.css');
 }
  public function index() {
 // Page specific resource 
$this->layout->js('js/lib2.js');
 $this->layout->css('css/page.css');
 $this->layout->title('Page title');
 $this->layout->view('index');
 } 
// This page uses different layout
  public function page2() {
 $this->layout_view = 'layout/short.php';
 $this->layout->title('Page title');
 $this->layout->view('index');
 }
 }
 ?>

 

Template Inheritance Like in Twig in CodeIgniter

Next area of improvement… Twig is a popular template engine available for PHP and it has a very nice feature called template inheritance. I personally do not see any practical usage of any template engines except PHP itself, but I love this feature and incorporated it here. Where to use it? Example: You want to implement breadcrumbs and they depend on what is current page. In your layout make a space for it anywhere with block function.

 

 <html>
 <head>
 <title>
<?=$title_for_layout?>
</title>
 <?=$css_for_layout?>
 <?=$js_for_layout?>
 </head>
 <body>
 <?$this->layout->block('breadcrumbs')?> 
Site | <?$this->layout->block()?>
 <?=$content_for_layout?>
 </body>
 </html>

 

In page template include block with same name and it would be replaced in layout with content generated in template.

 

 <?$this->layout->block('breadcrumbs')?>

 

Breadcrumbs for this page:

 

 <?$this->layout->block()?>

 

Page content! Download full code here. Comments are very welcome!