How I do layouts and views in CodeIgniter

I 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.

php sprintf + sql like

Sometimes I do my best programming when I’m tired. Don’t ask me why, I just do. It’s a skill I picked up in college.

Being tired and producing good code wasn’t the case last night. I was trying to use the sprintf PHP function with a SQL “Like” statement. I made some dumb mistakes that tripped me up for a while. Hopefully someone out there will find this post and help them not make the problems I made, sleepy or not!

Normally the LIKE is used in mysql like this:
SELECT name FROM users WHERE name LIKE 'J%';

That would get all names including: Josh, Jason, Jimi, etc.
In a SQL Like statement the % is a wild card, so the command is to match everything starting with “J”

Now when you use the sprintf() function it looks kind like this:
$query = sprintf("SELECT name FROM users WHERE name='%s'", $searchString);
The %s will be replaced with the value of $searchString

Trying to combined them is where I had some problems….

At first I tried to do something like this:
$query = sprintf("SELECT name FROM users WHERE name LIKE'%s'", $searchString);
didnt return what I was looking for at all, it had no wild cards in it!

Then I tried this:
$query = sprintf("SELECT name FROM users WHERE name LIKE'%s%'", $searchString);
didnt work either, this time it threw errors

But this worked great
$query =
sprintf("SELECT name FROM users WHERE name LIKE '%s'", $searchString . "%");

So the moral of the story is, if you want to use a SQL Like statement, appent the wildcard for the Like statement to the string to be inserted by the sprintf funtion.

Improving CodeIgniters View Handling

codeigniter logo

Please be aware that I no longer use this method. Please follow this link to see how I handle layout with Codeigniter

If you have ever worked with an MVC framework for web developent, you know that the “V” stands for “view”.

At work, I program in coldfusion, and use the coldbox framework, and I love it. At home, I write PHP code, with the codeigniter framework.

I love codeigniter, but I think that its biggest weakness is the view handeling, all thought codeigniter had taken strides to improve it. At the time of writing this, codeigniter is at version 1.6.1, and allows multiple views to be loaded at one time.

example:

<?php
 
class Page extends Controller {
 
function index()
 {
 $data['page_title'] = 'Your title';
 $this->load->view('header');
 $this->load->view('menu');
 $this->load->view('content', $data);
 $this->load->view('footer');
 }
 
}
 ?>

This is great with one exception, codeigniter simple builds a stack of the view results, appending them to each other.

This means that in header.php, loaded at the start of the view sequence, we would have to opening tags, such as <body>, and then in the last view, footer, we have to close the tags we opened in header.php, in this case, </body>

I don’t know about you, but opening tags in open file, and depending on another file to close them is not a good practice. Using a MVC setup and then doing something like this is very counter intuitive.

To fix this, codeigniter needs to support layouts, as well as views.

A layout is a file that contains the framework for a page, and the views are included and rendered inside the layout. basically filling out the content of the page. This also leaves your code the ability to be more flexible. Your views are pluggable components that don’t care about the layout at all.

One of the reasons I love open source software is the fact that the community will fix weaknesses is the software. Looking at the codeigniter wiki, I came across the “view object” (http://codeigniter.com/wiki/View_Object/)

The view object is a great solution for adding layouts to the codeigniter framework.
Here is a code sample of how to use the view object in a controller:

$this->load->library('view');         // or autoload
 
$this->view->layout = 'admin/layout';
 
$this->view->data(array(              // set the view data
 'privileges' => $privileges,
 'catcode'    => -1,
 'page'       => $page,
 ));
 
$this->view->load(array(             // load the page partials
 'header'     => 'header',
 'menu'       => 'menu',
 'content'    => 'admin/'.$page,
 'footer'     => 'footer',
 ));
 
$this->view->render();               // create the view or

inside the layout file (admin/layout.php)

<? $header->render(); ?>
 
<body>
 <? $menu->render(); ?>
 <div id="mainContent">
 <? $content->render(); ?>
 </div>
 </body>
 
<? $footer->render(); ?>

You can see that the layout file contains the framework of the page, freeing up the views to be individual pluggable items that can be used across your codeigniter application.

I hope that the codeigniter team takes note of the view object and adds it to the core for codeignier 1.7 or maybe even sooner!

LifeStreaming Is Simple As Pie

Its not secret, I love social networking, I cant get enough of it. I also love programming and anything internet related.

I’m not sure how I came across it, but a PHP based, Object Oriented RSS caching tool named SimplePie caught my attention.

Previously I had been using a tool called Last RSS, but I found that Last RSS could not handle ATOM feeds.

Digging into how SimplePie works, I found that I could merge several feeds together, sorted by post time, my first thought was to use this to aggregate and cache all the different music related news feeds that and going to add content to notpopular.com v2.5 (when ever I finish it). I started thinking about it a bit more and thought it would be cool to use SimplePie to mash together all of the different RSS feeds from the different social networks I am on.

It wasn’t that hard to use SimplePie and the various social networks to make something really cool.


//establish the feeds
$pownce = new SimplePie("$pownceRSS_url");
$flickr = new SimplePie("$flickrRSS_url");
$twitter = new SimplePie("$twitterRSS_url");
$digg = new SimplePie("$diggRSS_url");
$youtube = new SimplePie("$youtubeRSS_url");


//merge them all together!
$merged = SimplePie::merge_items(array($pownce, $flickr, $twitter, $digg, $youtube));

Then all you have to do is look over each item in $merged, and output the appropriate info you want.

You can see what I built over at www.JoshHighland.com

One thing I really found great was the API that was on the SimplePie site.

After I put this all together, I found out that there is a term for what I had just built. People are calling them “LifeStreams“, which is a very appropriate term. I thought I had invented something, but guess LifeStreaming is like fire or a spear, given enough time people all over the place will discover it on their own.

I encourage you do set up a LifeStream for yourself and post the URL in the comments below. It’s fun!

My LifeStream: www.JoshHighland.com

UPDATE (10/29/08) :
I was having trouble with my feed from twitter dying after a while. It would only fetch it once, then nothing.I found the answer to my problem on the simplePie blog, http://simplepie.org/blog/2008/08/16/twitter-bug/. I followed the instructions and commented out the If statement on lines 1583-1586, and the twitter feed started to work again. I hope that twitter updates their RSS service so hacks like this aren’t needed.

WordPress 2.5 image upload problem : SOLVED

This afternoon I upgraded my blog to the latest version of wordpress, 2.5. The install went great and it was simple to do. I didn’t realize that I had any problems until I went to make a blog post and upload an image. When I tried to upload, I was greeted with the following:

Something was for sure messed it. I tried it in several browsers, but had the same results. no luck. I started to go some searching online but since wordpress 2.5 is so new, there was little info to be found. After about an hour of stumbeling around I came across a post on a forum where someone said they got the image upload to work by adjusting their .htaccess file on thier site with the following code.

<IfModule mod_security.c>
<Files async-upload.php>
SecFilterEngine Off
SecFilterScanPOST Off
</Files>
</IfModule>

I made the change to my .htaccess file, and like magic the image upload feature started to work again!

I am making this post in the hopes that other people with similar problems will stumble across this post and be able to fix their problem with out having to wade through all the pages of people trying to diagnose what the problem is when the solution is super easy.