8 min read

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

LEAVE A REPLY

Please enter your comment!
Please enter your name here