close

Day 6: Get to grips with CodeIgniter

What is Codeigniter?

Codeigniter describes itself as “a powerful PHP framework with a very small footprint, built for PHP coders who need a simple and elegant toolkit to create full-featured web applications.”. It also provides the underpinnings for Expression Engine and powers a lot of sites across the web.

Derided by some due to it’s PHP roots it is, to my mind anyway, a brilliant way to go from idea to execution in a very short time. It also provides proper well documented avenues to extend it’s abilities.

Why Codeigniter?

In my quest to make my life as simple as possible, and being from a non-programming background, I’ve always felt more at home with things where there’s a decent bit of documentation. Obviously, being a typical web geek, I rarely read the documentation wholesale but rather I dip into it as and when required. In fact much like we all fell for JQuery over Prototype I’d suggest that the documentation is one of the makes things that makes Codeigniter stand head and shoulders above it’s competitors.

It’s also pretty small, very flexible and for non-programming types like me it’s all written on top of PHP which to my mind is the most accessible server side language on the web right now. Coupled with that the fact that it runs on just about any PHP environment with only a tiny bit of configuration and hopefully you are starting to see why I like it so much.

Another important part of any framework choice (and again why JQuery leads the field in JS frameworks) is the size and strength of the community. Codeigniter has lots of places to find help from the very friendly message boards on the Codeigniter site, the Codeigniter Community on StackOverflow to following the tweets of people like Phil Sturgeon and (the far too talented for his age) Jamie Rumbelow.

Getting Started

Some assumptions:

  • You speak ‘some’ PHP
  • You can get a LAMP/WAMP/MAMP environment working (See resources at the bottom of the article if you need any guidance)

You’ll also need a rough understanding of the MVC (Model, View, Controller) pattern. Models describe the data structures within your system, views render that data, and controllers provide the logic to take that data and render it in views, as well as offering more in-depth functions. See the resources at the end of the article for more guidance on this.

If you are happy with those then let’s get going!

First up head over to http://codeigniter.com/ and download yourself a copy of Codeigniter. Normally I would recommend a cup of tea of coffee whilst you wait but as Codeigniter is only a paltry 2.2mb you’ll have barely left your seat by the time it’s done.

Next up, extract it to a folder and configure your MAMP/XAMMP etc to point to that folder. If you want to make life really simple for yourself just extract it to the root of your web server (htdocs). if you need any further help have a read of the User Guide

Go to http://localhost/ (or where ever you configured it) and you should see this:

welcome_default

Our first Controller

The first thing Codeigniter does for you is map the URI to the controllers (you can overide the way it does this using the routes.php file in config but we’ll save that for another day) so, for example, http://localhost/account/ will call the index() function inside a controller named ‘account.php’, if you then created a function called login() inside the account controller you could access it by using the URI http://localhost/account/login/ . Any URI segments you pass beyond this will map as variables to your function eg:http://localhost/account/address/123 would pass the value 123 to an address function’s first variable eg: address($addressid).

Open up the file named welcome.php in the /application/controllers folder and add this code which will run a simple echo command.

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Welcome extends CI_Controller {
public function index()
{
echo 'Hello world';
}
}
/* End of file welcome.php */
/* Location: ./application/controllers/welcome.php */

Note that the class name (Welcome) has to be the same as the filename (welcome.php)

Now go to http://localhost/index.php and you should see:

welcome_hello_world

What horrible code!

As you can see we’ve used this amazingly powerful framework to echo a line of text to the screen and frankly that’s embarrassing so we’d better get onto something vaguely resembling MVC…

Create a file called greeting.php in the /application/views folder, so we can begin separating our code out nicely, and put this code inside it.

<?php echo $greeting; ?>

Now return to your welcome.php file in the /application/controllers/ folder and add the following after the end of the index function in order to call our view.

public function with_view()
{

//create an array to hold the data we wish to pass to the view
$data = array();
$data['greeting'] = 'Hello world';

//use the load view function to load 'greeting.php' and pass the $data array for the view to use
$this->load->view('greeting',$data);

}

Now go to http://localhost/index.php/welcome/with_view and you should see exactly the same thing you saw before. erm…

Obviously I’m kidding, the whole point here is we’ve wrapped some data up in an array and passed it to the view ‘greeting’ (Codeigniter adds the .php suffix automatically)

So that’s some pretty straightforward stuff which we can now easily modify to take a variable from the URI like this:

Add this function below the with_view function in controllers/welcome.php

public function with_view_and_var($name = 'Alun')
{

/* This will be fired by the uri /greeting/with_view/ */
/* and the next segment in the uri will be assigned to */
/* the variable $name if $name is not supplied then the */
/* function will default the value to be 'Alun' */

$data['greeting'] = 'Hello '.$name;

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

}

Now go to http://localhost/index.php/welcome/with_view_and_var/Santa and you will see:

welcome_with_view_and_var

Models

So now we’ve seen a View and a Controller but we’ve not done anything with the Models yet.

In Codeigniter it’s considered a standard to prefix all your Model files and class names with ‘M’ to make them easier to identify in the code eg MUsers, MProducts and so on.

Navigate to ‘/application/models/ and create a file called mgreetings.php and pop the following code inside which will allow us to retrieve some data:

<?php
class MGreetings extends CI_Model {

//always extend the Codeigniter model to enable the framework

function __construct()
{
/* Call the Codeigniter_Model's constructor */
/* You MUST do this in order to activate the */
/* default Codeigniter model */

parent::__construct();

}

function hello($lang)
{

//create an array of "greetings"

$hello = array();
$hello['en'] = 'Hello';
$hello['fr'] = 'Bonjour';
$hello['de'] = 'Guten Tag';
$hello['lol'] = 'Oh Hai';

/* check if a value has been found in the array */
/* if not default it to 'en' */

if( ! isset($hello[$lang]))
{

$lang = 'en';

}

return $hello[$lang];
}

}

And now reopen the welcome.php controller and add the following after the with_view_and_var function to call the “hello” function from our model:

public function with_model($lang = 'en')
{

//Load the model we just created
$this->load->model('MGreetings');

//Run the 'hello' method of the MGreetings model and
//assign it to the data['greeeting'] element
$data = array();
$data['greeting'] = $this->MGreetings->hello($lang);

//load the greeting.php view and pass the $data array to it
$this->load->view('greeting',$data);

}

And hopefully a visit to http://localhost/index.php/welcome/with_model/fr will yield something like this:

welcome_with_model_fr

and if you’ve been paying attention I hope you’ll see that you can add a language code to the end of the uri to get different greetings like this: http://localhost/index.php/greeting/with_model/lol

welcome_with_model_lol

Using databases

For this tutorial I’ll be using Codeigniter’s active record class. I’ll be using it for a number of reasons:

  1. It has a nice simple syntax
  2. It is easy to script lots of different variations using logic structures
  3. It handles stuff like XSS Filtering (Cross-site Scripting Hacks) when used in conjunction with Codeigniters built-in Input class. That’s not to say this code is safe to stick straight on the web (any update form needs to be protected from unauthorised users) but it’d be pretty robust to simpler attacks. For more information see the Codeigniter user guide.

Codeigniter has a whole bunch of configuration you can do. Thankfully for code-phobics like myself you only need to play with a few files. Later you’ll want to get more involved with these (especially the routes.php file) but for our purposes we only need modify the file ‘database.php’ and the ‘config.php’ file. Handily the config items are all stored in the ‘application’ folder.

The application folder should really be the only one that you ever need to play with, everything else is pretty much the Codeigniter core and version specific stuff. This also means if you need to upgrade just download the latest version and copy everything except the application folder over the top of your existing project. This can of course all be done using Git etc but as the last time I checked in a file in SVN it took my team a day to work out what I had done wrong I’m not going to instruct you on this!

There are 2 ways of telling Codeigniter to use the database library. First you can add $this->load->database(); into your code where ever you need it. You will soon tire of this… The second is to use another config file called autoload.php which can be found in the ‘/application/config/’ folder. Simply head to line 55 and change it to:

$autoload['libraries'] = array('database');

Codeigniter can now access the database via any controller or model (although you should never need to access it in a controller). do this now and we’ll save ourselves some typing…

First we need to create a database on your mySQL server, I’ve called mine 12devs but you can name yours anything you like (but not rude things, Santa wouldn’t approve)

Now run this SQL against your database to create a table and populate it with some data:

--
-- Table structure for table `greetings`
--

CREATE TABLE `greetings` (
`greetingid` int(11) NOT NULL AUTO_INCREMENT,
`lang` varchar(10) CHARACTER SET utf8 NOT NULL,
`text` varchar(255) CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`greetingid`)
) ;

--
-- Dumping data for table `greetings`
--

INSERT INTO `greetings` VALUES(1, 'de', 'Guten Tag ');
INSERT INTO `greetings` VALUES(2, 'en', 'Hello');
INSERT INTO `greetings` VALUES(3, 'fr', 'Bonjour');
INSERT INTO `greetings` VALUES(5, 'lol', 'Oh Hai');

So let’s head on over to the ‘/application/config/’ folder and modify database.php:

Modify line 51 onwards, you should know what settings you need but here’s mine for reference…

$db['default']['hostname'] = 'localhost';
$db['default']['username'] = '12devs';
$db['default']['password'] = 'password';
$db['default']['database'] = '12devs';

We also need to enable the XSS Filtering. Edit line 280 of ‘/application/config/config.php’ to read TRUE instead of FALSE

$config['global_xss_filtering'] = FALSE;

Next up we need to modify our greetings model to talk to the database, so go ahead and create a new function in ‘application/models/mgreetings.php’ like this:

function greeting($language = 'en')
{

//select the table to use
$this->db->from('greetings');

//add a where clause
$this->db->where('lang', $language);

//get all records that match
$this->db->select('*');

//limit to 1 response
$this->db->limit(1);

//run the query
$query = $this->db->get();

if($query->num_rows() != 0){
// return result set as an associative array
return $query->row();
}

}

Next we’ll add an additional function in welcome.php controller to show off our wonderful data driven model.

public function with_db_model($lang = 'en')
{
//load our Greetings model
$this->load->model('MGreetings');

//get 1 row back from the db
$greeting_row = $this->MGreetings->greeting($lang);

//grab the 'text' value from the object returned from the db
$data['greeting'] = $greeting_row->text;

//load the view with the required data
$this->load->view('greeting',$data);

}

You should now be FULLY underwhelmed by seeing the following when you visit http://localhost/index.php/welcome/with_db_model/de

welcome_with_db_model_de

So what is the framework ACTUALLY doing for me?

Ok, I haven’t given you much to go on here but we need to get some principles in place before we rush off to reinvent Twitter. Firstly by separating out the model and the view any time we ever need to get a greeting we can simply call $this->MGreetings->greeting($lang); rather than code it up hundreds of times across our app. This is often referred to as DRY: Don’t Repeat Yourself and is a worthwhile mantra in any coding pursuit.

Codeigniter is also mapping the URI to our controllers and passing variables over.

I’ve also not touched on helpers or libraries both those that are built into CodeIgniter and those you can either download from others or write yourself. A helper or a library is a discreet block of code that provides either a nice wrapper to hold related functionality or in other cases completely new functionality. Codeigniter has all these helpers and libraries* bundled and more: Array Helper, CAPTCHA Helper, Cookie Helper, Date Helper, Directory Helper, Download Helper, Email Helper, File Helper, Form Helper, Calendar Class, Cart Class, Email Class, Encryption Class, File Uploading Class, Form Validation Class, FTP Class, Image Manipulation Class, Input Class, and MANY, MANY more!

Make sure you take a look at the Codeigniter User Guide to see all of them

* Codeigniter calls classes libraries and vice versa

Forms & database interactions

Any site these days needs a form, whether it’s to let someone contact you or to steal your customers personal information to sell to the highest bidder to let someone update their status

The Codeigniter forms helper

Now we’re getting into helpers you’ll start to see the real power of using a framework. Need to build a form? Simple, call the form helper, drop a few lines of code and you are sorted. Doesn’t have HTML5 elements yet? No problem extend the helper easily to include them.

OK, lets crack on…

I’m going to rush through this last bit as time is running short but due to all the wonderful Codeigniter documentation anything you don’t understand you can easily look up plus I think granny is making a beeline for the last of the mince pies…

Create greeting_create.php in your /applications/views/ folder and insert the following code:

<?php echo validation_errors(); ?>
<?php
echo form_open();
echo form_fieldset('Add a new greeting');
?>
<div>
<?php
echo form_label('Language code', 'lang');
echo form_input('lang');
?>
</div>
<div>
<?php
echo form_label('Greeting text', 'text');
echo form_input('text');
?>
</div>
<div>
<?php
echo form_submit('mysubmit', 'Add a new greeting!');
?>
</div>
<?php
echo form_fieldset_close();
echo form_close();
?>

Now open up your /applications/controllers/welcome.php file and add the following function:

public function create()
{

//load the helpers we need
$this->load->helper('form');
$this->load->helper('url');

//load the library we need
$this->load->library('form_validation');


//set some validation rules
//for more info see http://codeigniter.com/user_guide/libraries/form_validation.html
$this->form_validation->set_rules('lang', 'Language code', 'required|is_unique[greetings.lang]');
$this->form_validation->set_rules('text', 'Greeting text', 'required');

//check to see if validation has run successfully
if ($this->form_validation->run() == FALSE)
{
//if not valid or not run then show our form
$this->load->view('greeting_create');
}
else
{

//assign the posted variables to an array
$data = array();
$data['lang'] = $this->input->post('lang');
$data['text'] = $this->input->post('text');

//load our Model
$this->load->model('MGreetings');

//create an array to store the greeting once we've commited it
$viewdata = array();
//commit the data to the database
$viewdata['greeting'] = $this->MGreetings->create($data);

//load the view with the data
$this->load->view('greeting_created', $viewdata);
}

}

Crete ourseleves a Thank You screen in the form of greeting_created.php inside the views folder:

Congratulations!

You created a new greeting with a language code of "<?php echo $greeting->lang;?>" and text of "<?php echo $greeting->text;?>"

Finally open up your /applications/models/MGreetings.php file and add the following functions:

function create($data)
{

//attempt to insert the contents of an array called data

if($this->db->insert('greetings', $data)){

//if successful find the data using the find() function and return it as an object

return $this->find($this->db->insert_id());
} else {

//return nothing, theres been a problem...
return false;
}

}

function find($id)
{

//tell the the 'db' object to use the 'greetings' table
$this->db->from('greetings');

//select everything from the 'greetings' table
$this->db->select('greetings.*');

//tell the 'db' object to add a WHERE clause
$this->db->where('greetingid', $id);

//limit the return to 1 item
$this->db->limit(1);
$query = $this->db->get();
if(num_rows() != 0){
// return a singe object containing the data
return $query->row();
}

}

Hopefully you’ll input some data and it’ll be added to the db…

One thing I hope you’ll notice (especially if you are the type like me who likes to try and break things) when you hit “Add a new greeting!” with duff information and the form validation runs the form is returned to you empty. BAD FORM! A quick fix is to use the form helper function ‘set_value’ like so:

<?php echo validation_errors(); ?>
<?php
echo form_open();
echo form_fieldset('Add a new greeting');
?>
<div>
<?php
echo form_label('Language code', 'lang');
echo form_input('lang', set_value('lang'));
?>
</div>
<div>
<?php
echo form_label('Greeting text', 'text');
echo form_input('text',set_value('text'));
?>
</div>
<div>
<?php
echo form_submit('mysubmit', 'Add a new greeting!');
?>
</div>
<?php
echo form_fieldset_close();
echo form_close();
?>

Give it a go and you should see the values being preserved when a validation error occurs.

A quick demo using a third party library

As I mentioned earlier the community around Codeigniter is amazing. Loads of libraries are available and they are rarely charged for, just remember to give back code if you find modifications that help or perhaps even write your own libraries and make them available.

Google maps in 5 minutes…

One of the things you might find me doing from time to time is organising the GeekKarting series of events across the UK so I’m going to quickly show you how to plot a few potential GeekKarting venues on a Google map using as few lines of code as possible…

Without a shadow of doubt the best library for Google Maps is Steve Marks’ superb Google Maps Codeigniter library. It provides a great way of producing google maps on your pages including festures such as clustering, custom markers and so on. It also has a PDF full of documentation on all its features. So go ahead and download it from here.

Copy the contents of the downloaded Google maps library’s archive /application/libraries/ to your /application/libraries/ folder in your Codeigniter project

Create a database table

Run this SQL to create some locations for the map to render:

--
-- Table structure for table `locations`
--

CREATE TABLE `locations` (
`locationid` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8 NOT NULL,
`description` text CHARACTER SET utf8 NOT NULL,
`longitude` decimal(12,10) NOT NULL,
`latitude` decimal(12,10) NOT NULL,
PRIMARY KEY (`locationid`)
);

--
-- Dumping data for table `locations`
--

INSERT INTO `locations` VALUES(1, 'Daytona Milton Keynes', 'Daytona Milton Keynes is the UK’s ultimate outdoor karting venue, boasting two exceptional race tracks complemented by excellent hospitality & conferencing facilities in the centre of Milton Keynes. Our Circuits are flood lit so operational from 9am to 10pm.', 52.0406330000, -0.7846640000);
INSERT INTO `locations` VALUES(2, 'Daytona Sandown Park', 'Daytona Sandown Park is an exceptional kart racing venue, boasting two circuits complemented by excellent hospitality and conferencing facilities in the heart of Surrey.', 51.3755210000, -0.3622890000);
INSERT INTO `locations` VALUES(3, 'Daytona Manchester', 'Daytona Manchester - the UK''s Premier Indoor Karting Venue - is our centrally-heated karting stadium located near Manchester city centre - and close to the world-famous Old Trafford Football ground.', 53.4661870000, -2.3020300000);

Create the model

Create a file called mlocations.php in your /application/models/ folder and insert this code into it:

<?php
class MLocations extends CI_Model {

function __construct()
{
// Call the Model constructor
parent::__construct();
}

function get()
{

$query = $this->db->get('locations');

return $query->result();

}

}

Create the view

Create the map.php file in your /application/views/ folder

Insert this code:

<html>
<head><?php echo $map['js']; ?></head>
<body>
<?php echo $map['html']; ?>
</body>
</html>

Create the controller

Create the geekkarting.php file in your /application/controllers/ folder

Insert this code:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class GeekKarting extends CI_Controller {

public function index()
{

}

}

/* End of file geekkarting.php */
/* Location: ./application/controllers/geekkarting.php */

Create the locations() function in the Geekkarting Controller which will grab some data from the database and assign it to the GoogleMaps library.

public function locations()
{

//load our new MLocations model
$this->load->model('MLocations');

//grab our data
$locations = $this->MLocations->get();

//load Steve's library
$this->load->library('googlemaps');


//set config
$config = array();
$config['zoom'] = 'auto';

//initialize the library using the config
$this->googlemaps->initialize($config);

//check we got some data back from our DB call
if($locations)
{
foreach($locations as $location)
{

//assign data from the array to a new array for use in the Google maps library
$marker = array();
$marker['position'] = $location->longitude.','.$location->latitude;
$marker['infowindow_content'] = '<h2>'.$location->name.'</h2>';
$marker['infowindow_content'] .= '<p>'.$location->description.'</p>';

//add a marker using the array we just created
$this->googlemaps->add_marker($marker);

}
}

$data['title'] = 'Potential GeekKarting Venues';
$data['map'] = $this->googlemaps->create_map();

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

}

Now head on over to http://localhost/index.php/geekkarting/locations/ and inspect your amazing work which should hopefully look a little bit like:

geekkarting_locations

There’s an elephant in this room…

I’ve tried to gloss over it but it is one of the niggles of Codeigniter that it doesn’t ship with a decent .htaccess file to get rid of the index.php in the url. Being no expert on all things .htaccess I can merely point you to some guidance in the Codeigniter notes which I hope will fix things for you.

The end

Well hopefully you’ve seen just how simple it is to get started with Codeigniter, although I’ve covered a fair bit I’ve only scratched the surface of what you can do. All I ask i return is the following:

  • Let me know what things you end up building with Codeigniter
  • When you discover something cool in Codeigniter give back to the community, let us hear about it too.
  • If you get very, very rich freelancing with Codeigniter please buy me a Lotus Evora S
  • And finally, make sure you come along to a Geek Karting event in the future and say Hi!