How I do layouts and views in CodeIgniter

codeigniter logo How I do layouts and views in CodeIgniterI have been a loyal fan of the kick-ass php framework, codeIgniter, for some time now. A while back I made a post on how to improve the view handling of codeIgniter. I would like to retract that post. Through the comments on that post I found out about an undocumented parameter (as of version 1.7, it has been documented) that allows view to be rendered into a variable. This changes everything, and totally negates any of the complaint I had about how CI handles layouts and views.

Below is an example of live code I have running at loudsongs.com. It shows how I have been able to take advantage of of this powerful third parameter that stops CI from rendering a view to the screen when loading it.


Inside of my controller

function index()
 {
 $base_url = base_url();
 
//what the nav needs
 $navigation_data['navTab'] = "home";
 
//basic info for the header
 $layout_data['pageTitle'] = "LoudSon.gs";
 $layout_data['meta_description'] = "Under Ground Lyrics, hardcore, metal, emo, rock";
 $layout_data['meta_keywords'] = "lyrics,song,songs,words,hardore,metal,emo,rock";
 $layout_data['meta_url'] = "$base_url";
 $layout_data['meta_classification'] = "home";
 $layout_data['searchInput'] = "";
 $layout_data['searchOptions'] = "";
 
$this->load->model('search');
 $lastest_albums = $this->search->last_n_albumsAdded(10);
 $popular_songs = $this->search->popular_n_songs(10);
 
//get the featured Albums
 $featuredAlbums = $this->search->getFeaturedAlbums();
 
$body_data['featured'] = $featuredAlbums;
 $body_data['newest'] = $lastest_albums;
 $body_data['popular'] = $popular_songs;
 
//load the content variables
 $layout_data['content_navigation'] = $this->load->view('navigation', $navigation_data, true);
 $layout_data['content_body'] = $this->load->view('home/homePage', $body_data, true);
 
$this->load->view('layouts/main', $layout_data);
 }

/views/navigation.php

<div id="header">
 <h1 title="Loud Songs Logo">LoudSongs search - hard to find obscure lyrics</h1>
 
<ul title="navigation">
 <li <? if($navTab == "about"){echo " id=\"active\"";}?>><a href="<?= base_url(); ?>about" title="About Page">About</a></li>
 <li <? if($navTab == "add"){echo " id=\"active\"";}?>><a href="<?= base_url(); ?>add" title="Add Lyrics">Add Lyrics</a></li>
 <li <? if($navTab == "home"){echo " id=\"active\"";}?>><a href="<?= base_url(); ?>" title="Home Page">Home</a></li>
 </ul>
 </div>

/views/home/homePage.php

<div>
 Thanks for visiting LoudSongs
 <br/>
 We are trying to build a maintain a collection of punk rock, hardcore, emo, metal and other lyrics.
 This website is free and open to all.
 Please help us by <a href="http://www.LoudSon.gs/add">contributing to the collection</a>.
 </div>
 
<div>
 <? $this->load->view('home/featuredAlbums'); ?>
 </div>
 
<div class="middle_col_split">
 <? $this->load->view('home/recentlyAdded'); ?>
 </div>
 
<div class="middle_col_split">
 <? $this->load->view('home/mostPopularSongs'); ?>
 </div>

/views/layouts/main.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html;charset=us-ascii">
 <meta name="description" content="<?= $meta_description ?>">
 <meta name="keywords" content="<?= $meta_keywords ?>">
 <meta http-equiv="expires" content="0" />
 <meta name="classification" content="<?= $meta_classification ?>" />
 <meta name="Robots" content="index,follow">
 <meta name="revisit-after" content="2 Days">
 <meta name="language" content="en-us">
 
<link href="<?= base_url() ?>includes/styles/lyrics.css" rel="stylesheet" type="text/css" media="screen" title="default">
 
<script language="javascript" type="text/javascript" src="<?= base_url() ?>includes/scripts/jquery-1.2.6.min.js"></script>
 
<title><?= $pageTitle ?></title>
 </head>
 
<body id="home">
 <div id="nav">
 <?= $content_navigation; ?>
 </div>
 
<div id="middle_column">
 
<?= $content_body ?>
 
</div>
 </body>
 
</html>


wow, ok, so that might be a lot to digest. The bottom line is this, CI doesnt have “layouts” like other frameworks, so you have to become creative and use a view AS a layout by using the mythical 3rd parameter when loading a view. We load data into the navigation view and store all of that into the $layout_data array, then we load a view named homePage and pass data into it, and stor it into the $layout_data array. When we are done loading all of the views into the array, we pass that array into another view. This view acts as our layout. easy as that! check it out below:

//load the content variables
 $layout_data['content_navigation'] = $this->load->view('navigation', $navigation_data, true);
 $layout_data['content_body'] = $this->load->view('home/homePage', $body_data, true);
 
$this->load->view('layouts/main', $layout_data);

I hope this helps someone understand how codeigniter does have layout and view functionality, you just have to structure it that way in your code.

post some comments if you need more clarification.

25 Comments

  1. The model doesn’t matter in this example. All I am doing is setting data in the controller and passing it to the views. How those views can be used as a layout is the purpose of this example

  2. Thank you, I’m porting from Zend Framework to CI mainly because of the ability to run CI web pages on php 4 and I real felt the lack of the layout resource. This actually is a good way of doing it and actually really simple.

    CI is, indeed, THE framework but not for everyone actually. You must have some background on PHP and object oriented paradigm. Once you get used to it you can do everything with CI and quickly.

    Thanks for the tip.

    Best regards, Chuckytuh.

  3. Great tutorial, Josh!

    I have recently started playing around with PHP/CI and I like what I have found so far. I, too, ran across the layout problem and your ideas really helped.

    However, have you figured out a way to reuse the code that builds the partials from page to page? For example, if you are going to have the $content_navigation across all your pages, so that you don’t have to rebuild the content variables for each method in your controller such as:

    $layout_data[‘content_navigation’] = $this->load->view(‘navigation’, $navigation_data, true);

    Regards,

    Saint

  4. Really nice approach of doing layouts! Thanks.

    I created My_Controller in which I pass site-specific options and I can override those on a per-page basis with your method, something that isn’t possible with the approach offered on the CI site. You should post your take there!

  5. Hi there. First of all, great little article about the CI framework. I found nothing wrong with your approach. I have known about this approach to load a view into a variable and the only case I’ve used it so far is when I want to send an HTML email using Ci’s email class. It *has* to be done this way. To answer Saint’s question: I solved the problem this way. I always load a single template file and pass it all the required variables for the content part of the page, along with info such as the name of the content file and page title. The template file then takes care of stitching the page together. Hope this helps.

  6. Very organized and makes for a tidy view.

    Do you think if you were working as the sole developer on a project and there was a web designer assigned to handle all the views, do you think it’d be less of a hassle for the designer to handle the meta, keywords, etc… in the view and keep the designer out of the controller?

  7. I think it all depends on the business logic, and who is in charge of that sort of task. In some case, I’ve had my meta tags managed by a database, in that case they have to be accessed from a controller. If it’s a less structured system, they is no problem with coding them in a view or layout

  8. Very useful explanations, i’m new in CI and i will try this excellent idea. I have been looked for this for a long time, great thanks for you “Master”.

  9. great tutorial. this is what I need. I hope this similar approach is integrated to the core CI. CI may have manuals but they lack design or cookbook details.

  10. Very nice article .. thanks a lot …
    But I was wondering how I can implement side-navigation with main navigation.. so every page loaded from top menu would have a different side menu, but when a link is clicked on the side menu, that menu should stay the same.
    Is it possible or to I have to load it each time with my view from the main navigation?
    Thanks!

  11. Hi Josh, great tutorial. As this was written 3 and a half years ago do you have any updates or revisions to make to it? There may be some new features of CI which make this stuff easier (I wouldn’t know though!). Thanks again!

Leave a Comment.