Getting Started With CodeIgniter – 6

Extending The Controller Class for Common Code

I’d like to thank Noah Botimer for his interest and assistance. I’ve now changed the way I’ve constructed my fledgling web application. This code replaces the code shown in Getting Started With CodeIgniter 5.

Because I wanted to have a certain amount of common code in all controllers – calls to two functions called setup_assets and setup_system_data in my case, I have now extended the controller class by using the MY_ technique.

The MVC example is below.

The Extended Controller Class

This is placed in system/application/libraries/MY_Controller.php
[php]
<?php
class MY_Controller extends Controller {

function __construct(){
parent::__construct();
$this->setup_assets();
$this->setup_system_data();
}

function setup_assets(){
$this->load->database();
$this->load->model(‘systemdata’);
$this->data[‘base_url’] = $this->systemdata->get_base_url();
$this->data[‘cssmain’] = $this->systemdata->get_cssmain_filespec();
$this->data[‘pdf’] = $this->systemdata->get_pdf_filespec();
$this->data[‘cssIE6’] = $this->systemdata->get_cssie6_filespec();
$this->data[‘cssIE7’] = $this->systemdata->get_cssie7_filespec();
$this->data[‘scripts’] = $this->systemdata->get_scripts_filespec();
$this->data[‘css’] = $this->systemdata->get_css_filespec();
$this->data[‘xml’] = $this->systemdata->get_xml_filespec();
$this->data[‘flash’] = $this->systemdata->get_flash_filespec();
$this->data[‘site_images’] = $this->systemdata->get_site_images_filespec();
$this->data[‘images’] = $this->systemdata->get_images_filespec();
$this->data[‘public_status’] = $this->systemdata->get_public_status();
$this->data[‘member_status’] = $this->systemdata->get_member_status();
}

function setup_system_data(){
$this->data[‘page_name’] = $this->systemdata->get_page_name();
$this->data[‘copy_right_range’] = $this->systemdata->getcopyrightrange();
$this->data[‘current_year’] = $this->systemdata->selectcurrentyear();
$this->data[‘version’] = $this->systemdata->selectwebsiteversion();
$this->data[‘global_phone’] = $this->systemdata->selectglobalphone();
$this->data[‘uk_phone’] = $this->systemdata->selectukphone();
$this->data[‘any_phone’] = $this->systemdata->selectanyphone();
}
}
?>
[/php]

A Controller

[php]
<?
class Privacy extends MY_Controller {
var $data;

function Privacy(){
parent::__construct();
$this->load->helper(‘url’);
}

function index(){
$this->load->view(‘publicuser/viewprivacy’, $this->data);
}

}
?>
[/php]

Getting Started With CodeIgniter – 5

One Controller Per View in CodeIgniter

So how do you break a website into views and controllers exactly? If you read the CodeIgniter forums people have devised lots of different ways of tackling the controller problem.

For me, taking the project I am currently working on, I find it easy enough to think in terms of objects for the tours, the shopping cart, a customer and so on. But the static web pages – the views that end up being your about, contact me, terms and conditions and privacy pages – how do you break down the controllers for those?

This is an especially testing question because you are likely to hit it pretty quickly when you decide to learn CodeIgniter and the MVC approach at the same time. You’re likely after all to want to start with simple pages.

First I thought – I’ll do one controller per view no matter how straightforward the page content. Then as soon as I had decided that, doubts crept in. No way! That’s absurd. How can you have one controller for the about page, another for the company history page and yet another for the terms and conditions page. They’d be practically the same!

Changed My Mind – One Catchall Controller for All Static Views

So I set about creating a common controller that would control all static pages. By static, I mean pages that only contained text that would rarely change.

Hmm – what was I going to call it – maybe the content controller (content.php), or maybe the static controller (static.php)? I was having trouble finding a good name for this catchall controller. This seemed to me like a sign I was on the wrong track.

The next thought that came to mind was – well hang on, I might want to add something data flavoured to the About page one day – I don’t know – it might be a feed of the client’s Twitter tweets. What then, the about page would suddenly no longer be hopelessly static and if I’d had the foresight to create one controller per page at the start, I wouldn’t have to change the general content controller for all static pages, just because one needed more.

Back to One Controller Per View

I am now back to the one page per controller idea. This meant however that each controller for each static page, necessarily contained a lot of repeated code. I hunted through the CodeIgniter forums for the best way to address this, and the answer appeared to be to use a helper.

I say ‘appeared’ as the CI forums can get very technical and sometimes, I am not not sure what they are all talking about. Hence the need to write this stuff on my blog I suppose.

Here’s a list of forum posts that I found useful whilst getting my head around this.

Using A Helper for Common Controller Code

If you decide to use one controller per view, you can cut down on repeated code by putting the common controller set up code (data loads etc) into a specially written helper. I wrote one called commoncontrol_helper.php and put it in the application/helpers directory. My helper looks like this, and contains (currently) one function called setup_assets. This follows on from my previous posts in this series.

[php]
<?php

function setup_assets($theobject){
$theobject->load->model(‘systemdata’);
$theobject->load->database();
$theobject->data[‘css’] = $theobject->systemdata->get_css_filespec();
$theobject->data[‘pdf’] = $theobject->systemdata->get_pdf_filespec();
$theobject->data[‘cssIE6’] = $theobject->systemdata->get_cssie6_filespec();
$theobject->data[‘cssIE7’] = $theobject->systemdata->get_cssie7_filespec();
$theobject->data[‘scripts’] = $theobject->systemdata->get_scripts_filespec();
$theobject->data[‘xml’] = $theobject->systemdata->get_xml_filespec();
$theobject->data[‘flash’] = $theobject->systemdata->get_flash_filespec();

$theobject->data[‘base_url’] = $theobject->systemdata->get_base_url();
$theobject->data[‘site_images’] = $theobject->systemdata->get_site_images_filespec();
$theobject->data[‘images’] = $theobject->systemdata->get_images_filespec();
$theobject->data[‘public_status’] = $theobject->systemdata->get_public_status();
$theobject->data[‘member_status’] = $theobject->systemdata->get_member_status();
$theobject->data[‘page_name’] = $theobject->systemdata->get_page_name();
$theobject->data[‘currentyear’] = $theobject->systemdata->selectcurrentyear();
}
?>
[/php]

And consequently, a controller that uses this helper will look like this :

[php]
<?php
class Privacy
extends Controller {
var $data;

function Privacy(){
parent::Controller();
$this->load->helper(‘url’);
$this->load->helper(‘commoncontrol’);
setup_assets($this);
}

function index(){
$this->load->view(‘publicuser/viewprivacy’, $this->data);
}

}
?>
[/php]

Getting Started With CodeIgniter – 4

Constructing the Home Page

This is what my home page looks like now. 

A Note About Graphics and Design

I’ll step you through how I did this using CodeIgniter. By the way, I did all the graphic elements myself or with the use of graphics tools. I am not a graphic designer so I fumble my way around the design of a site. I get hold of any easy to use graphics tools that are available. I’ve done another post that lists the tools l used.

While we are on the subject, the colours used on this site are not my choice – the site owner chose them.

Now back to CodeIgniter.

The General Idea

  1. I created a home page and called it viewhome.php, then placed it in the views folder within CodeIgniter’s directory structure. Actually, I placed it in a sub-directory of the views folder which I called /publicuser.

    Although many pages will be for public consumption, there will also be admin and member pages, so I’m planning ahead and having three sub-directories in the views folder to keep them separate.

    I also created some include files to use as the header and footer parts of the page. These were named include-header.php and include-footer.php and placed in the same sub-directory. 

  2. A file called home.php was also created as a controller for viewhome.php and this was placed in the controller folder within a /publicuser sub-directory.
  3. There is also a model file called systemdata.php.  This was placed directly into in the model folder.  The systemdata.php file is named to indicate that it manages all the system level data. So, at this point I had my basic MVC set-up.
  4. I placed my CSS file in the CSS sub directory of the assets folder that I mentioned in an earlier post. Javascript files were put into the js sub directory or the assets directory, and so on as previously described. All graphics files were also placed in either the images or site-images sub directories.
  5. In the model file called systemdata.php, I placed all the system wide referencees to data – including references to CSS and Javascripts – so that I could refer to them from any controller.

OK – that was the basic idea. Now for the precise steps to achieve it.

config.php

The idea of the config file is to place all the data that can perhaps vary from installation to installation, or perhaps that you want to define once and forget about. This is certainly true of stuff like the name and location of various external files like images, css files and javascript files.

In reality there would be many more (flash, pdf etc), but this is just to give you an idea.

I keep all such external assets in the assets sub-directory off the application folder. The naming of the assets directory is my choice, you can call it what you like – it is not part of the CodeIgniter installation. It’s existence is up to you.

A Note About base_url

In the config file I have two values for base_url. This makes it easy to switch from running the code on your local machine to running on your server. You just comment out the base_url value that you are not using.

[php]
$config[‘base_url’] = "http://localhost//chaingang3/";
//$config[‘base_url’] = "http://www.example.com/test1";

$config[‘css’] = "/system/application/assets/css/my.css";
$config[‘scripts’] = "/system/application/assets/scripts/";
$config[‘site_images’] = "/system/application/assets/site-images/";
$config[‘images’] = "/system/application/assets/images/";
[/php]

routes.php

I want the home.php controller to be called when someone visits my site’s home page (www.example.com or www.example.com/index.html). In order to effect this, you have to change a parameter in the routes.php file which you will find in the config sub-directory.

When CodeIgniter is first installed, the routes.php file will say :
[php]
$route[‘default_controller’] = "welcome";
[/php]

Change routes.php by commenting out the old line and replacing it with the name of your entry controller. Mine is called home.php, so
[php]
//$route[‘default_controller’] = "welcome";
$route[‘default_controller’] = "publicuser/home";
[/php]

The Model

I have to start with, one model that I’ve called systemdata.php as it contains just that. Within this model, I am not accessing a database for the moment, but mostly just the config data that we just placed in the config file.

It’s pretty convoluted but we have managed to separate the data from the view from the control.
If you end up wanting to change the location of the images say, you can do it in one place – in the config file.

[php]
class Systemdata extends Model {

function Systemdata(){
parent::Model();
}
function get_css_filespec(){
return $this->config->item(‘css’);
}
function get_scripts_filespec(){
return $this->config->item(‘scripts’);
}
function get_base_url(){
return $this->config->item(‘base_url’);
}
function get_images_filespec(){
return $this->config->item(‘images’);
}
function get_site_images_filespec(){
return $this->config->item(‘site_images’);
}
}
[/php]

The View

My home page is called viewhome.php. The only reason I call it viewhome.php and not home.php say, is because I get mixed up with what is a view, and what is a controller otherwise. I therefore have a convention that says, call the controller the plain name (in this case home.php), then place “view” in front of that name to arrive at the name of the view. Works for me.

So viewhome.php is a home page and has the following basic format (note I have pared this down as much as possible so as to only include the essential CodeIgniter information). Also note that I use PHP short-tags <%%>

[php]
<head>
<link rel="stylesheet"
type="text/css" href="<%=$base_url%><%=$css%>" />
<script type="text/javascript"
src="<%=$base_url%><%=$scripts%>myscripts.js"></script>
</head>
<body>
<%=$this->load->view("publicuser/include-header");%>

<h1>My New Website</h1>
<p>
Lots of interesting information
</p>

<%=$this->load->view("publicuser/include-footer");%>
</body>
[/php]

The Controller

Here is the controller, in my case home.php. Again I have cut it down to the bare minimum.

I load the helpers url and html and the database class but these are for later and not pertinent to what I am showing you now.

Next I load the model systemdata, then proceed to use it to extract the filenames and locations that I set up in the config file.

There is enough in this article to get you to a very simple home page, and get you set up to create everything else you need in a more complex web application. It was this basic structure that I found hard to get started.

[php]
class Home
extends Controller {
var $data;

function Home(){
parent::Controller();

$this->load->helper(‘url’);
$this->load->helper(‘html’);
$this->load->database();
$this->load->model(‘systemdata’);

$this->data[‘css’] = $this->systemdata->get_css_filespec();
$this->data[‘scripts’] = $this->systemdata->get_scripts_filespec();

$this->data[‘base_url’] = $this->systemdata->get_base_url();
$this->data[‘site_images’] = $this->systemdata->get_site_images_filespec();
$this->data[‘images’] = $this->systemdata->get_images_filespec();
$this->data[‘scheme’] = $this->systemdata->get_scheme();
}

function index(){
$this->load->view(‘publicuser/viewhome’, $this->data);
}

}
[/php]

Running The Site

I test the site locally – that is how the config file has been set up – the root has been defined to be the root of my webserver, as in :
[php]
$config[‘base_url’] = "http://localhost//chaingang3/";

[/php]

To run the site type the following into your browser address window :
[php]
http://localhost/chaingang3/index.php

[/php]

As I’ve mentioned before, I tend to use one controller per view. It helps me keep control. But other people have other ways. The best thing is to read the CodeIgniter forums and see what everyone has to say. I found this article on controllers particularly helpful.

Getting Started With CodeIgniter – 3

Model – View – Controller

CodeIgniter implements the MVC (model – view – controller) design pattern. Writing web pages this way can help to separate how a page looks, from its data and also from its flow of control.

Views

When you write a web page in CodeIgniter you are encouraged to place all the visible stuff – the way the page looks, into a view page.

Models

Next you do your best to place all the data related stuff into a model page. This doesn’t just mean data in databases, but can also mean anything that counts as data on the page.

You can stretch this to encompass almost anything and you’ll see that I use a model to pass the name of any CSS and JS files I use, to a page.  I mean, you could just hard-wire those things directly into a view, but I have chosen not too.

Controllers

And you are supposed to place all the flow of control, or processing stuff, inside a controller page.

There are no hard and fast rules for doing this, and the way I’ve structured my web pages for the MVC approach may be frowned on by some.  However, my purpose in showing you how I do it here, is to get you started. Once you’ve seen how I tend to structure things you can makes your own changes and improvements.

Views and Controllers

I’d like to say a bit more about these. If you’re writing a program to send a rocket to the moon, and you’re writing it using object oriented techniques, you’d write a bunch of classes to represent the objects in your program.  You might for example, write the class rocket, and the class moon.

You ‘d probably then write methods (functions) like rocket.launch and have properties like moon.temperature. In fact everything (in other words all functions and data) you ever want to calculate or say about moons or any number of rockets will be encapsulated in the moon and various rocket objects.

The whole idea of OO programming is to keep relevant coding material in once place, to encourage strategic thinking about programming design, make code re-use come naturally, encourage clarity and to discourage the computing scourge of the 1970s, spaghetti code.

But What About Ordinary Web Pages?

But in web design, controllers and models are also classes and as such we should try to split the various classes up to somehow reflect the world.  I found this to be a tough call when using CodeIgniter for a business web site. After all, what are the objects when all you have to start with is a few web pages?

You could argue that CodeIgniter is an overkill for small sites, but to my mind, small sites have the potential  to grow so you may as well start out the way you mean to carry on . . .

MVC for Your Web Site

I assume that when I need to add the real database functionality the objects will be obvious, but in order to set up the basic, (practically) database free site, I create a class for each page. Yes – that means I have a  contact class and an about me class and a home class . . . .

In my next post, Getting Started With CodeIgniter – 4, I’ll list everything I do to get a home page up and running using the MVC model.

Getting Started With CodeIgniter – 2

Getting The Environment Set Up

Last time, we installed the software and altered the config.php file by adding two lines (one commented out). Please review Getting Started With CodeIgniter – 1 for details.

If you now visit the home page running locally on your PC, you should see this. Obviously you must substitute your root directory where I have used chaingang3.

Setting up database.php

Most web sites demanding the attentions of CodeIgniter will need a database. I am using MySQL. I created a MySQL database called chaingang3 and set up a username and password for it.

To communicate this to the CI system, edit the database.php file located in the config directory (same place as the config.php file was located).

Add the following lines to database.php, but of course use your own username, password and database name.  The placeholders for these parameters are already in the file, you just have to fill in the values.

[php]
$db[‘default’][‘hostname’] = "localhost";
$db[‘default’][‘username’] = "myusername";
$db[‘default’][‘password’] = "mypassword";
$db[‘default’][‘database’] = "chaingang3";
[/php]

Setting Up constants.php

I like to place any constants that I need to have available throughout the web site in the constants.php file. So early in your development you won’t know what these are for the mostpart, but each time you need a new global constant, set it up in here. To start with I will put in the Version number of the site I am developing. This is the site’s 3rd version so I’ll make a suitable constant, and add it to constants.php.

[php]
define(‘WEBSITE_VERSION’, ‘3.0’);

[/php]

Setting Up Custom Functions

As you code, you’ll need to write PHP functions.  There is a special place to put these in CI. Go to system/application/helpers and create a custom helper PHP file with a name like mycustomfunctions_helpers.php.

For example, one function I always add to my custom helper file is something to alert PHP values without having to write the Javascript each time. This is symptomatic of my never using a debugger.  Here it is :

As time goes on, you’ll add more of your own functions to this file.

Sub Directories for Image, CSS, Javascript and Other Files

I put all the images that are part of the web design into a sub directory called site-images and all content images into a sub-directory called images. Further, I like to place all my CSS files into a css sub-directory and Javascript files into a sub-directory called scripts. I follow the same regime for any other special files the web site may need  – like say for example a sub-directory for flash movies, another for PDFs and so on.

To do this, create all your required sub-directories under the CI application directory in a new sub-directory called assets.  Of course you don’t have to call it assets – I do because someone on the CI forums suggested the name. Anyway – I set the following structure up and so I’ll always have somewhere specific to place required files.