Navigating Your Site using CodeIgniter 1.7: Part 2

Exclusive offer: get 50% off this eBook here
CodeIgniter 1.7

CodeIgniter 1.7 — Save 50%

Improve your PHP coding productivity with the free compact open-source MVC CodeIgniter framework!

€18.99    €9.50
by David Upton | November 2009 | MySQL PHP Web Development

In this article by Jose Argudo Blanco and David Upton, we will cover the following:

  • How to pass parameters to controllers using the URL
  • How to write better views and pass dynamic data to them
  • How a reply is returned to the surfer
  • How the files or classes pass information and control to each other
  • How useful code is kept inside helper and library files
  • Some practical hints on site design

Read Navigating Your Site using CodeIgniter 1.7: Part 1 here.

Designing a better view

At this stage, you might ask: Why are we going through so much effort to serve a simple HTML page? Why not put everything in one file? For a simple site, that's a valid point—but whoever heard of a simple site? One of the coolest things about CI is the way it helps us to develop a consistent structure. So, as we add to and develop our site, it is internally consistent, well laid out, and simple to maintain.

At the start, we need to take these three common steps:

  • Write a view page
  • Write a stylesheet
  • Update our config file to specify where the stylesheet is

After this is done, we need to update our controller to accept parameters from the URL, and pass variables to the view.

First, let's redesign our view and save it as testview.php, at /www/codeigniter/application/views/testview.php.

<html>
<head>
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0
Strict//EN'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
<html xmlns='http://www.w3.org/1999/xhtml'>
<title>Web test Site</title>
<link rel="stylesheet" type="text/css" href="<?php echo
$base."/".$css;?>">
</head>
<body>
<h1><?php echo $mytitle; ?> </h1>
<p class='test'> <?php echo $mytext; ?> </p>
</body>
</html>

It's still mostly HTML, but notice the PHP "code islands" in the highlighted lines. You'll notice that the first bits of PHP code build a link to a stylesheet. Let's save a simple stylesheet as styles.css, at www/codeigniter/css/styles.css. It just says:

h1
{
margin: 5px;
padding-left: 10px;
padding-right: 10px;
background: #ffffff;
color: blue;
width: 100%;
font-size: 36px;
}
.test
{
margin: 5px;
padding-left: 10px;
padding-right: 10px;
background: #ffffff;
color: red;
width: 100%;
font-size: 36px;
}

This gives us two styles to play with, and you'll see we've used both of them in the view. Firstly, let's add an entry to the config file:

$config['css'] = 'css/styles.css';

This is simply to tell the name and address of the CSS file that we've just written to the site. But note that the link to the stylesheet is referenced at $base/$css: Where do those variables, $base and $css, get their values? And come to think of it, those variables $mytitle and $mytext at the end of the code? We need a new controller!

Designing a better controller

Now, we need a new controller. We'll call it Start and save it as start.php, at /www/codeigniter/application/controllers/start.php.

This controller has to do several things:

  • Call a view
  • Provide the view with the base URL and the location of the CSS file we just wrote
  • Provide the view with some data—it's expecting a title ($mytitle) and some text ($mytext)
  • Lastly, accept a parameter from the user (that is using the URL request)

In other words, we have to populate the variables in the view. So let's start with our Start controller. This is an OO class:

<?php
class Start extends Controller
{
var $base;
var $css;

Notice that here we've declared the $base and $css (the CSS filename) as variables or class properties. This saves us from having to redeclare them if we write more than one function in each class. But you can define and use them as local variables within one function, if you prefer.

The constructor function now defines the properties we've declared, by looking them up in the config file. To do this, we use the syntax:

$this->config->item('name_of_config_variable');

As in:

function Start()
{
parent::Controller();
$this->base = $this->config->item('base_url');
$this->css = $this->config->item('css');
}

CI recovers whatever we entered in the config file against that name.

Using this system, no matter how many controllers and functions we write, we'll have to change these fundamental variables only once. This is true even if our site becomes so popular that we have to move it to a bigger server.

Getting parameters to a function

Now, within the Start controller class, let's define the function that will actually do the work.

function hello($name = 'Guest')
{
$data['css'] = $this->css;
$data['base'] = $this->base;
$data['mytitle'] = 'Welcome to this site';
$data['mytext'] = "Hello, $name, now we're getting dynamic!";
$this->load->view('testview', $data);
}

This function expects the parameter $name, but you can set a default value—myfunction($myvariable = 0), which it uses to build the string assigned to the $mytext variable. Well, as we just asked, where does that come from?

In this case, it needs to come from the URL request, where it will be the third parameter. So, it comes through the HTTP request:

http://127.0.0.1/codeigniter/start/hello/Jose

This example code doesn't "clean" the passed variable Jose, or check it in any way. You might want to do this while writing the code. We'll look at how to check form inputs. Normally, variables passed by hyperlinks in this way are generated by your own site. A malicious user can easily add his or her own, just by sending a URL such as: http://www.mysite.com/index.php/start/hello/my_malicious_variable. So, you might want to check that the variables you receive are within the range you expect, before handling them.

The last segment of the URL is passed to the function as a parameter. In fact, you can add more segments of extra parameters if you like, subject to the practical limits imposed by your browser.

Let's recap on how CI handles URLs, since we've covered it all now:

URL segment

 

What it does

 

http://www.mysite.com

 

The base URL that finds your site.

 

/index.php

 

Finds the CI router that sets about reading the rest of the URL and selecting the correct route into your site. If you have added the .htaccess file in the previous chapter, this part will not be visible, but will still work as supposed.

 

/start

 

The name of the controller that CI will call (If no name is set, CI will call whichever default controller you've specified).

 

/hello

 

The name of a function that CI will call, inside the selected controller (If no function is specified, it defaults to the index function, unless you've used _remap).

 

/Jose

 

CI passes this to the function as a variable.

 

If there is a further URL segment, for example, /bert

 

CI passes this to the function as the second variable.

More variables

 

CI will pass further URL segments as consequent variables.

 

Passing data to a view

Let's go back to the hello function:

function hello($name)
{
$data['css'] = $this->css;
$data['base'] = $this->base;
$data['mytitle'] = 'Welcome to this site';
$data['mytext'] = "Hello, $name, now we're getting dynamic!";
$this->load->view('testview', $data);
}

Notice how the hello() function first creates an array called $data, taking a mixture of object properties set up by the constructor and text. Then it loads the view by name, with the array it has just built as the second parameter.

Behind the scenes, CI makes good use of another PHP function—extract(). This takes each value in the $data array and turns it into a new variable in its own right. So, the $data array that we've just defined is received by the view as a series of separate variables; $text (equal to "Hello, $name, now we're getting dynamic"), $css (equal to the value from the config file), and so on. In other words, when built, the $data array looks like this:

Array
(
[css] => 'mystyles.css';
[base] => 'http://127.0.0.1/packt';
[mytitle] => 'Welcome to this site';
[mytext] => 'Hello, fred, now we're getting dynamic!';
)

But on its way to the view, it is unpacked, and the following variables are created in the view to correspond to each key/value pair in the array:

$css = 'mystyles.css';
$base = 'http://127.0.0.1/packt';
$mytitle = 'Welcome to this site';
$mytext = 'Hello, fred, now we're getting dynamic!';
)

Although you can only pass one variable to a view, you can pack a lot of information into it. Each value in the $data array can itself be another array, so you can pass pieces of information to the view in a tightly structured manner.

Now navigate to http://127.0.0.1/codeigniter/start/hello/jose (note that the URL is different—it is looking for the start function we wrote in the index controller) and you'll see the result—a dynamic page written using MVC architecture. (well, VC at least! We haven't really used the M yet).

You can see that the parameter jose is the last segment of the URL. It has been passed into the function, and then to the view. Please remember that your view must be written in parallel with your controller. If the view does not expect and make a place for a variable, it won't be displayed. If the view is expecting a variable to be set and it isn't, you are likely to get an error message (your view can of course accept variables conditionally).

Also, a controller can use more than one view; this way we can separate our pages into sections such as the header, the menu, and so on. Each of these views can be nested one inside the other. Child views can even inherit variables passed by the controller to their parent view.

Loading a view from inside another view is very easy; just put something like this PHP snippet in your HTML code:

<body>
<div id="menu">
<?php $this->load->view('menu'); ?>

This way we can load a view inside a view, with all variables in the first one also available into the nested one.

CodeIgniter 1.7 Improve your PHP coding productivity with the free compact open-source MVC CodeIgniter framework!
Published: November 2009
eBook Price: €18.99
Book Price: €30.99
See more
Select your format and quantity:

How CI classes pass information and control to each other

As you write your controllers, models, and so on, you will need to pass control and data between them. Let's look at some of the ways in which we can do this.

Calling views

We have seen how the controller calls a view and passes data to it. First it creates an array of data ($data) to pass to the view, loads it, and calls the view in the same expression:

$this->load->view('testview', $data);

Calling functions directly

If you want to use code from libraries, models, plugins, or helpers, you have to load them first, and then call them as described in the previous table. So, if display is a model and I want to use its mainpage function, my controller might call:

$this->display->mainpage();

If the function requires parameters, we can pass them to the function like this:

$this->display->mainpage('parameter1', $parameter2);

Interacting with controllers

You can call libraries, models, plugins, or helpers from within any controller, or model; libraries, plugins, and helpers can also call each other.

However, you can't call one controller from another or a controller from a model or library. There are only two ways in which a model or a library can refer back to a controller:

  • It can return data if the controller assigns a value such as this:
    $fred = $this->mymodel->myfunction();

    Using this, the function is set to return a value, which will be passed to the variable $fred inside the controller.

  • Your model or library can create (and send to a view) a URL, which allows a human user to call the controller functions. Controllers are there to receive human interactions.

You can't, of course, hyperlink directly to a model or library. Users always talk to controllers, never to anything else; however you can write a calling function in the controller. In other words, your view might contain a hyperlink to a controller function:

echo anchor('start/callmodel', 'Do something with a model');

The callmodel function would exit only to call a function in the model:

function callmodel()
{
$this->load->model(mymodel);
$this->mymodel->myfunction();
}

An example of a CI helper—the URL helper

As an example you can split your code into neat, focused chunks. CI's URL helper contains a set of functions that help you to manipulate URLs. You load it like this:

$this->load->helper('url');

You can also use it to find and return the site and/or base URLs that you set in your config file:

echo site_url();
echo base_url();

You can also use it to create hyperlinks. In the last section, we saw how to access the hello function in the start controller and pass the parameter fred to it, with a URL such as:

http://www.mysite.com/index.php/start/hello/fred

If you want your code to create a hyperlink to a URL, you can use the URL helper to do it. The syntax is:

echo anchor('start/hello/fred', 'Say hello to Fred');

This generates a hyperlink to the same URL, and displays the words Say hello to Fred for the user to click on. In other words, it's an equivalent of:

<a href="http://www.mysite.com/index.php/start/hello/fred ">Say hello
to Fred</a>

Remember, there are two advantages to using the CI helper. Firstly, less typing required—49 characters as opposed to 82, both including spaces. If you include another 27 characters loading the URL helper, which you have to do once per controller, it still comes to 76 rather than 82.

Secondly, the URL helper automatically looks up the site URL in the config files (and the index file name). This means that if you change your site location, you only need to alter the config file once. You don't have to hunt through your code for hyperlinks that don't work any more.

The URL helper has other useful functions. For instance, it can create a mailto hyperlink such as:

echo mailto('me@example.com', 'Click Here to Email Me');

It has the same effect as typing this HTML:

<a href="mailto:me@example.com">click here to email me</a>

If you are worried about robots harvesting the email addresses from your website and using them for spamming, change mailto in the CI code to safe_mailto. What appears on your viewer's screen is exactly the same, and works the same way.

However, if you examine the actual HTML code, this has now become a complex heap of JavaScript, which the robot cannot (easily) read:

<script type="text/javascript">
//<![CDATA[
var l=new Array();
l[0]='>';l[1]='a';l[2]='/
';l[3]='<';l[4]='|101';l[5]='|109';l[6]='|32';l[7]='|108';l[8]='|105'
;l[9]='|97';l[10]='|109';l[11]='|101';l[12]='|32';l[13]='|111';l[14]=
'|116';l[15]='|32';l[16]='|101';l[17]='|114';l[18]='|101';l[19]='|72
';l[20]='|32';l[21]='|107';l[22]='|99';l[23]='|105';l[24]='|108';l[25
]='|67';l[26]='>';l[27]='"';l[28]='|109';l[29]='|111';l[30]='|99';l[3
1]='|46';l[32]='|101';l[33]='|108';l[34]='|112';l[35]='|109';l[36]='|
97';l[37]='|120';l[38]='|101';l[39]='|64';l[40]='|101';l[41]='|109';
l[42]=':';l[43]='o';l[44]='t';l[45]='l';l[46]='i';l[47]='a';l[48]='m'
;l[49]='"';l[50]='=';l[51]='f';l[52]='e';l[53]='r';l[54]='h';l[55]='
';l[56]='a';l[57]='<';
for (var i = l.length-1; i >= 0; i=i-1){
if (l[i].substring(0, 1) == '|') document.write("&#"+unescape(l[i].
substring(1))+";");
else document.write(unescape(l[i]));}
//]]>
</script>

You and your users need never see this code. It's only there to confuse the robots and keep your email addresses safe from spam. You put it there by adding four letters and an underscore, where you wrote safe_mailto instead of mailto, and CI did the rest.

There are several other useful functions in the URL helper. Take a look at the user guide, where you will find some helpful ones:

http://codeigniter.com/user_guide/helpers/url_helper.html

Just consider the URL helper as a whole. Let's go back to the touchstones for coding, which we discussed earlier in this article:

  • This code has high "component singularity". It does a limited range of things, and it's clear what they are.
  • It is "loosely coupled"—it has a simple interface and no dependency on any code that's calling it. You can use the URL helper in any CI project you're writing. Most of your projects will need some sort of hyperlinks. You can use this helper over and over again to create them.

If you look at the URL helper's code in /www/codeigniter/application/helpers/url_helper.php, you'll see that it is procedural code, that is, it is simply a set of functions, not an OO class. It doesn't load any other CI classes or helpers (not being an object it can't do this directly).

A simple library example—creating a menu

Now let's look at some code that uses the CI classes. For instance, here is a simple library file that creates a menu with three choices. You can save it in /www/codeigniter/application/libraries/menu.php:

1 <?php
2 class Menu{
3 function show_menu()
4 {
5 $obj =& get_instance();
6 $obj->load->helper('url');
7 $menu = anchor("start/hello/fred","Say hello to Fred |");
8 $menu .= anchor("start/hello/bert","Say hello to Bert |");
9 $menu .= anchor("start/another_function","Do something else |");
10 return $menu;
11 }
12 }
13 ?>

For the moment, don't worry about the unusual syntax—$obj-> rather than $this->, on line 6.

Note that this code is now OO code, in which the function show_menu() is contained in a single class, that is Menu. It can access other CI classes and helpers; in this case it is using the URL helper, which we just examined.

First it loads the URL helper and then it creates a string ($menu), consisting of HTML code for hyperlinks to the three controllers and functions specified. Then it returns the $menu string.

You might call it from a controller like this:

$this->load->library('menu');
$mymenu = $this->menu->show_menu();

The controller can then use the $menu variable to call a view:

$data['menu'] = $mymenu;
$this->load->view('myview', $data);

After that you will only have to put an echo $menu in your view file, which will produce a site-specific menu. For this reason, we have saved it in the /www/codeigniter/application/libraries, rather than the /CI_system/libraries folder. It's not as loosely coupled as the URL helper, which I can use on any site.

It does have high singularity—it creates a menu, and that's all it does. It can be called from any controller in the site and it will show the standard menu in the view.

Summary

The MVC pattern is a widely used and is a very effective way of organizing a complex website. CI uses it to help you sort your own code, but it is also fairly flexible about how it does so.

The crucial thing is to understand what the different type of files are, and how they relate to each other. Then, you can decide whether to write your code in library or model files, or as helpers or plugins.

We've looked at the CI file structure, and seen how you can, if you want, inspect  all the CI code, but (thankfully!) you don't have to. We did tinker with one of the original files—the config file, which holds critical site information in one place to make it easy for us to upgrade or change later.

We've seen the basic object structure of a controller, and used a simple constructor to get some data from our config file and put it into a class property. We've dynamically passed information from a new controller we wrote, to a new view. So far, the main thing CI has done for us is to encourage us to use a basic structure as we start to define our site. As we go on, it will become clear just how important that structure is.

Also, we looked at the way in which CI's components pass data and control between themselves. It's useful to understand this when you start to write your code. Lastly, we looked at CI's own URL helper as a good example of a chunk of code, and we wrote our own rudimentary menu library class.

[ 1 | 2 ]

 

If you have read this article you may be interested to view :

 

CodeIgniter 1.7 Improve your PHP coding productivity with the free compact open-source MVC CodeIgniter framework!
Published: November 2009
eBook Price: €18.99
Book Price: €30.99
See more
Select your format and quantity:

About the Author :


David Upton

David Upton is a director of a specialized management consultancy company, based in London but working around the world. His clients include some of the world’s largest companies. He is increasingly interested in web-enabling his work, and seeking to turn ideas into robust professional applications by the simplest and easiest route. He has so far written applications for two major companies in the UK. His other interests include simulation, on which he writes a weblog which takes up far too much of his time, and thinking.

Books From Packt

jQuery UI 1.7: The User Interface Library for jQuery
jQuery UI 1.7: The User Interface Library for jQuery

jQuery 1.3 with PHP
jQuery 1.3 with PHP

Symfony 1.3 Web Application Development
Symfony 1.3 Web Application Development

PHP Team Development
PHP Team Development

ICEfaces 1.8: Next Generation Enterprise Web Development
ICEfaces 1.8: Next Generation Enterprise Web Development

Grails 1.1 Web Application Development
Grails 1.1 Web Application Development

Seam 2.x Web Development
Seam 2.x Web Development

Apache MyFaces Trinidad 1.2: A Practical Guide
Apache MyFaces Trinidad 1.2: A Practical Guide

Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software