A look at codeigniter

We’re using Codeigniter at university in our second term, so naturally I had to look at it during the holiday break before it started. Codeigniter is a PHP MVC framework. I prefer it to writing PHP from scratch, but my personal opinion is that I still like Catalyst more. Yet again, Catalyst is Perl based, while Codeigniter is PHP.

Anyway, I’m going to look into making a simple registration and login system from scratch. The first step is, of course, to download codeigniter. You can get it from its website. You unzip the file somewhere where your webserver will service it, and check it out on your browser. Congratulations, you have the most basic setup ready!

Looking at the contents of your new folder, application/ has all the things you should care about. Specifically, config/ has all the configuration-related stuff, controllers/ is where the controllers go, models/ is where the models go, and views/ is where the views go.

The best place to start is the config. Having a look at the application/config folder we first have config.php which has some global settings. There are a few things you may want to change there, but nothing that will prevent the application from working. If accepting user input, however, I like to enable CSRF protection and XSS protection. In that file you can find

$config['csrf_protection'] = FALSE;
$config['csrf_token_name'] = 'csrf_test_name';
$config['csrf_cookie_name'] = 'csrf_cookie_name';
$config['csrf_expire'] = 7200;

You can change that to something like:

$config['csrf_protection'] = true; //You need to set this to true,
$config['csrf_token_name'] = 'token'; //but these settings can be
$config['csrf_cookie_name'] = 'token'; //whatever you want.
$config['csrf_expire'] = 7200;

Then, codeigniter will take care of CSRF protection for you! There’s also this:

$config['global_xss_filtering'] = FALSE;

If you change that to true, you will get global XSS protection. There are other settings in the file you may want to change, so look around.

Next important file is application/config/database.php. If you’re doing anything database related, then you need to edit that. It’s pretty self explanatory, but

$db['default']['hostname'] = 'localhost';
$db['default']['username'] = '';
$db['default']['password'] = '';
$db['default']['database'] = ''; //You may want to create a database for your app
                                 //And put its name here.
$db['default']['dbdriver'] = 'mysql';

Is what you absolutely need to change. For the driver, I suggest mysqli and not the default value of mysql, since it has been deprecated for ages.

There’s also application/config/routing.php which determines how routing works in your app. We’ll look at that in a bit though.

Now that the config part is done with for now, we can take a first look at controllers. If you look at application/controllers/welcome.php You have a very basic controller that basically does this:

public function index()
{
      $this->load->view('welcome_message');
}

index() is called when a user goes to http://your_website/index.php/welcome/, but because the routing config (see above) chooses ‘welcome’ as the default controller, http://your_website/ will load the same page.
In fact, you could do this:

public function hello()
{
      $this->load->view('welcome_message');
}

And then http://your_website/index.php/welcome/hello will display the same message.
You might guess where that page comes from: application/views/welcome_message.php – change that page and the page displayed when you load the welcome page will be loaded.

Of course the whole point is to make your own views, controllers and models. Since we want to make a registration system, it’s probably good to start from the database. We’ll make a users table:

CREATE TABLE IF NOT EXISTS `users` (
  `user_name` varchar(255) NOT NULL,
  `user_id` bigint(255) unsigned NOT NULL AUTO_INCREMENT,
  `password` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL,
  PRIMARY KEY (`user_id`),
  UNIQUE KEY `unique_user` (`user_name`,`email`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;

We can then make a model to reflect this database table. You can create all your models in application/models, so this would be application/models/user_model.php or similar

<?php

    if ( !defined('BASEPATH') ) {
        exit('No direct script access allowed');
    }

    class user_model extends CI_Model {
        public function __construct() {
            $this->load->database(); //load the database class
        }

        public function login() {
            $username = $this->input->post('username');
            $password = $this->input->post('password');

            $query    = $this->db->get_where (
                'users',
                array (
                    'user_name' => $username
                )
            );

            $user     = $query->row();

            if ( !$user ) {
                return -1; //no such username
            }

            if ( $password != $user->password ) {
                return 0; //wrong password
            }

            $_SESSION['user'] = $user->user_id;
            return 1; //correct
        }

        public function register() {
            $password   = $this->input->post('password');

            $data = array (
                'user_name'    => $this->input->post('username'),
                'password'     => $password,
                'email'        => $this->input->post('email')
            );

            $this->db->insert ('users', $data);

            $_SESSION['user'] = $this->db->insert_id();
        }
    }
?>

This is pretty self explanatory. It loads the database class, and defines a login function that checks if the database data matches the input data and a register one that inserts to the database. get_where allows you to get results for a where query, and insert inserts an array of keys and values to the specific database fields. You may see that we don’t check the input here. This is ok, we’ll do this in our controller.

Now that we have our model we need a couple views. application/views/register.php:

<?php
    $this->load->helper('form');
    echo form_open('register/submit');
?>
        <fieldset>
            <label>
                <legend>Register</legend>
                <label>
                    User name:<br/>
                    <input type="text" name="username" value="" />
                </label><br/>
                <label>
                    Email:<br/>
                    <input type="email" name="email" value="" />
                </label><br/>
                <label>
                    Password:<br/>
                    <input type="password" name="password" value="" />
                </label><br/>
                <input type="submit" name="" value="register" />
            </label>
        </fieldset>
    </form>

You may notice that instead of a >form< tag we use form_open. The reason for this is that this method also takes care of inserting the counter-CSRF fields if we enabled this in the config.

Similarly, application/views/login.php:

<?php
    $this->load->helper('form'); //this form helper gives us form_open
    echo form_open('login/submit');
?>
        <fieldset>
            <label>
                <legend>Login</legend>
                <label>
                    User name:<br/>
                    <input type="text" name="username" value="" />
                </label><br/>
                <label>
                    Password:<br/>
                    <input type="password" name="password" value="" />
                </label><br/>
                <input type="submit" name="" value="login" />
            </label>
        </fieldset>
    </form>

And now we can actually make our controllers, which will be simple since we have our user model ready.
This is our register controller – application/controllers/register.php

<?php
    session_start();

    class register extends CI_Controller {
        public function __construct() {
            parent::__construct();
            $this->load->model('user_model'); //load our user model
            //When you load it, you can use all its methods through
            //$this->user_model
            $this->load->helper('form'); //and the form helper
        }

        public function index() {
            $this->load->view('register'); //just display the form
        }

        public function submit() {
            $this->load->library('form_validation');//load the form validation lib

            $this->form_validation->set_rules(
            'username',
            'Username',
            'required|max_length[255]|is_unique[users.user_name]'
            ); //this will ensure the username isn't already in the database,
               //that it's been provided,
               //and that it's no more than 255 chars long
            $this->form_validation->set_rules('password',
            'Password', 'required|max_length[55]');
            $this->form_validation->set_rules('email', 'Email',
            'required|valid_email|is_unique[users.email]');
             //Similarly, this will ensure
             //The email is unique and valid.

            if ( $this->form_validation->run() === false ) {
                $this->index(); //if the form validation fails show the index
            } else {
                $this->user_model->register();
                //this will create the db record from input
                //do something else
                //If you want to redirect a user to a page after this:
                $this->load->helper('url');
                redirect('/user/show_info');
            }
        }
    }
?>

We can see how codeigniter made our lives easier here. Instead of writing the same boring validation methods again and again we get them provided to us, plus the database helper doesn’t hurt either.

the login controller will be like this:

<?php
    session_start();

    class login extends CI_Controller {

        public function __construct() {
            parent::__construct();
            $this->load->model('user_model');
            $this->load->helper('form');

        }

        public function index($error="") {
            $this->load->view('login', array ('error' => $error));
        }

        public function submit() {
            $this->load->library('form_validation');

            $this->form_validation->set_rules('username', 'Username', 'required');
            $this->form_validation->set_rules('password', 'Password', 'required');

            if ( $this->form_validation->run() === false ) {
                $error = 'Please provide a username and password';
                $this->index($error);
            } else {
                $result = $this->user_model->login();

                if ($result == -1) {
                    $error = "No such username";
                    $this->index($error);
                } elseif ($result == 0) {
                    $error = 'Wrong password!';
                    $this->index($error);
                } else {
                    //Success!
                    //Again, you can now...
                    $this->load->helper('url');
                    redirect('/user/show_info');
                }
            }
        }
    }
?>

You might have noticed two things in the above. 1: Where do validation errors go? 2: What does

   $this->load->view('login', array ('error' => $error));

do?

As for the first question, the answer is validation_errors(). It’s a method of our form helper and you can use it in your view:

<?php
        if (validation_errors()) {
?>
            <div class="error">
                <?php
                    echo validation_errors();
                ?>
            </div>
<?php
        }
?>

And for the second question, this just passes a variable into the view. This means we can do:

<?php
if (isset($error)) {
?>
    <div class="error">
        <?php
            echo $error;
        ?>
    </div>
<?php
}
?>

You can use this to pass any required data to your model, such as database query results, etc.

Congratulations, you should now have a working login system! You can of course see this in action at http://your_app/index.php/register/ and
http://your_app/index.php/login respectively.

If you want to be able to view a user’s information after that, you can add a function to get a user object from their id to your model:

<?php

    if ( !defined('BASEPATH') ) {
        exit('No direct script access allowed');
    }

    class user_model extends CI_Model {
        public function __construct() {
            $this->load->database(); //load the database class
        }

        public function by_id($user_id) {
            //does a SELECT query WHERE user_id = $user_id
            $query    = $this->db->get_where (
                'users',
                array (
                    'user_id' => $user_id
                )
            );

            //returns an object represening the resulting user row in the database
            return $query->row();
        }        

        public function login() {
            $username = $this->input->post('username');
            $password = $this->input->post('password');

            $query    = $this->db->get_where (
                'users',
                array (
                    'user_name' => $username
                )
            );

            $user     = $query->row();

            if ( !$user ) {
                return -1; //no such username
            }

            if ( $password != $user->password ) {
                return 0; //wrong password
            }

            $_SESSION['user'] = $user->user_id;
            return 1; //correct
        }

        public function register() {
            $password   = $this->input->post('password');

            $data = array (
                'user_name'    => $this->input->post('username'),
                'password'     => $password,
                'email'        => $this->input->post('email')
            );

            $this->db->insert ('users', $data);

            $_SESSION['user'] = $this->db->insert_id();
        }
    }
?>

And then you can use this from a controller:

<?php
    //application/controllers/user.php
    session_start();

    class user extends CI_Controller {
        public function __construct() {
            parent::__construct();
            $this->load->model('user_model');
        }

        public function show_info($user_id=false) {
            if ($user_id == false) { //default to our logged in user
                $user_id = $_SESSION['user'];
            }
           
            $user = $this->user_model->by_id($user_id);
            //this will make $user available to your view
            $this->load->view('info', array('user' => $user));
        }
    }
?>

the view could be just:

<?php
//application/views/info.php
echo "Hello " . $user->user_name . ".";
?>

or anything else that uses the $user object! It should have all the values from your database row available.

now link_to_your_site/user/show_info/{user_id} will display the user’s name.

The next thing to do from here is to look at The manual to look at how helpers work and other awesome things you can do.

Until next time,

4 thoughts on “A look at codeigniter

  1. Hi Errietta Kostala,

    This is a gr8 peace of wrk from u…

    I have one security query about http only cookies, I think earlier CI had $config[‘cookie_httponly’]
    configuration but now in the latest version it is unavailable.

    cld u pls tell me whether I can change it from core session library

    ->system/libraries/session.php
    ->function _set_cookie()

  2. Hi nice to meet you. Sorry I am newbie on codeigniter. I wonder if you could show how to run the application http://localhost:1234/WEBSERVICE/index.php/login and you can see username and password, and how to connect database on mysql using codeigniter?, but I still dont understand of your tutorial about CSRF protection and XSS protection using token like this :

    $config[‘csrf_protection’] = FALSE; $config[‘csrf_token_name’] = ‘csrf_test_name’; $config[‘csrf_cookie_name’] = ‘csrf_cookie_name’; $config[‘csrf_expire’] = 7200;
    You can change that to something like:

    $config[‘csrf_protection’] = true; //You need to set this to true, $config[‘csrf_token_name’] = ‘token’; //but these settings can be $config[‘csrf_cookie_name’] = ‘token’; //whatever you want. $config[‘csrf_expire’] = 7200;
    Then, codeigniter will take care of CSRF protection for you! There’s also this:

    $config[‘global_xss_filtering’] = FALSE;

    and where could i learn more about connection codeigniter for web services. Because I want to call data from mysql with big data then show them.

  3. I try to insert the database username,userid:1,email with my name but when enter to the website on http://localhost:1234/WEBSERVICE/index.php, there is an error like this :

    A Database Error Occurred

    Error Number: 1046

    No database selected

    SELECT * FROM (`users`) WHERE `user_name` = ‘muhammad.iqbal’

    Filename: C:\xampp\htdocs\WEBSERVICE\system\database\DB_driver.php

    Line Number: 331

    on DB_driver.php i change the var like this :

    from
    var $username’;
    var $password ;
    var $hostname’;
    var $database;

    to :

    class CI_DB_driver {

    var $username = ‘root’;
    var $password = ”;
    var $hostname = ”;
    var $database = ”;
    var $dbdriver = ‘mysql’;

    • You need to choose the database name in application/config/database.php – e.g. $db[‘default’][‘database’] = ‘YOUR DATABASE NAME’; //You may want to create a database for your app
      Make sure you’ve created it of course (with the mysql command line or phpmyadmin)

Leave a Comment

Your email address will not be published. Required fields are marked *