Creating a CodeIgniter App (Part 2): Installation

In this post I’ll show how to set up your CodeIgniter installation properly and start our Task Board app. For this purpose we will also define two database tables and a simple installation procedure. This post is part of the “Creating a CodeIgniter App” and continues what started with the Introduction.


Let’s start this article with a little bit of planning. Our goal is to build the Simple Task Board app from scratch. In order to complete our goal, this is our agenda for the following weeks:

  1. Introduction (already published)
  2. Installation: CodeIgniter installation, database (users and sessions) and app install procedure
  3. Login: login, creation of a simple Template library and layout (menus)
  4. Users: edit/add/remove users
  5. Projects: database (projects), view project tasks (task board), edit/add project
  6. Tasks: database (tasks), edit/add tasks

This is just the first version of the Simple Task Board app. So, when I update it, I’ll add new posts to this list to explain how the update was done. Let’s get this thing going.


First thing we’ll do is download the latest version of CI (CodeIgniter). Get the ZIP file and extract its contents into your desired folder (I’m doing it into localhost/task_board_tutorial). You will need a server properly installed in your local machine or a hosting service, but I’m assuming you already know this (if you need help, let me know in the comments). Next thing is remove the user_guide folder. We won’t need it because we can get all the information online. This is what you should see:

  • application
  • system
  • index.php
  • license.txt

If you go to http://localhost/task_board_tutorial this is what you will see:

Welcome to CodeIgniter

Now go to the application/config folder. We’re going to update some files here:


As you may have guessed, this is where most of the configuration is done. Let’s change the following lines:

$config['base_url'] = 'http://localhost/task_board_tutorial/';

The base_url will be used by CI to build the links in your app. So, when you create an anchor using the anchor() function, this value will be used to create the full link.

$config['index_page'] = '';

Remove the value for the index page. If you leave the index.php value your links will look like http://localhost/task_board_tutorial/index.php/controller/method instead of http://localhost/task_board_tutorial/controller/method. But we also need to use an htaccess file to make it work. So, go back to your root folder and create a .htaccess file with the following contents:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /task_board_tutorial/index.php/$1 [L]

You need the Apache mod_rewrite for this. This is not part of this tutorial, so if you have any trouble, let me know in the comments. Now, let’s go back to the config.php file.

$config['encryption_key'] = 'j4Hg4sptw39HTE26dOIncYT67dH6yfi2';

As we are going to use the Session class provided by CI, we need to define an encryption_key. It needs to be 32 characters long and as random as possible. You can, and should, create your own one. Please check the official reference.

$config['sess_cookie_name'] = 'stb_session';

$config['sess_use_database'] = TRUE;

Let’s change the session cookie name to stb_session (stb as in Simple Task Board :D). We are going to use our database for session controlling, so change sess_use_database to TRUE. The database table name will remain the same, so we don’t need to change it. At this point you can increase or decrease the session expiration (sess_expiration). That’s all we need to change for the config.php file.


The database.php file contains the database connection settings. So, if you haven’t created a MySQL database for this tutorial, do it now. With the database created, get the necessary information and update this file accordingly.

$db['default']['hostname'] = 'localhost';
$db['default']['username'] = 'root';
$db['default']['password'] = '';
$db['default']['database'] = 'task_board';

We don’t need to change the other settings.


The routes.php file is a powerful one. It let’s you change the URL “handling” by setting your own routes – meaning you can force a URL to go to a different controller/method.  If you change a lot of stuff here, it may be hard for another developer to figure out what your application is doing, because the default behavior will be overwritten. Anyway, in our case we just want to do a simple change.

$route['default_controller'] = "login";

Change the default_controller from welcome to login.  When we go to http://localhost/task_board_tutorial, CI will get the name of the default controller from here, so we are sending it directly to the login controller (that we will create later).

Now we are finished with the CI installation. It is time to go to your phpmyadmin or your preferred MySQL application.


There are only two database tables that we need at this point, user and ci_sessions (used by CI to manage sessions). So grab the following scripts and execute them in your database.


  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `email` varchar(255) NOT NULL,
  `password` varchar(40) NOT NULL,
  `level` tinyint(4) NOT NULL,
  `date_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email` (`email`)

The user table will have the ID, email, password, level and the date it was created.


  `session_id` varchar(40) NOT NULL DEFAULT '0',
  `ip_address` varchar(16) NOT NULL DEFAULT '0',
  `user_agent` varchar(120) NOT NULL,
  `last_activity` int(10) unsigned NOT NULL DEFAULT '0',
  `user_data` text NOT NULL,
  PRIMARY KEY (`session_id`),
  KEY `last_activity_idx` (`last_activity`)

This is a standard table for CI, and you can get it from the user guide.

Installation Procedure

Now let’s do some coding. As our database is empty, we need a procedure to create a first entry in the user table and allow us to do the login. This is what we will do next:

  • Create the model (user_model.php) inside the application/models folder.
  • Create the controller (install.php) inside the application/controllers folder.
  • Create the view (login.php) – we will use the same file as the login one – inside the application/views folder.


Create the file in the application/models folder and add the following content:


class User_model extends CI_Model {
    private $salt = 'r4nd0m';

    public $USER_LEVEL_ADMIN = 1;
    public $USER_LEVEL_PM = 2;
    public $USER_LEVEL_DEV = 3;

This class will contain all our model methods and properties. The first property is the $salt, which will be used to help encrypting our passwords. You are strongly recommended to change that… We also define 3 user levels as different properties. From now on, I’m going to show which methods we will need for the installation procedure. All these methods should go inside the class.

    public function get($id = false)
        if ($id) $this->db->where('id', $id);
        $this->db->order_by('email', 'asc');
        $get = $this->db->get('user');

        if($id) return $get->row_array();
        if($get->num_rows > 0) return $get->result_array();
        return array();

The get method is responsible for retrieving information from the database. As you can see, we are using here the database library ($this->db). In order to use it, we need to load it first. Why am I not doing it here? Because we can use the autoload.php to automatically load it for us. So, open config/autoload.php and set the following:

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

Why we do it like that? Because we are using the database pretty much everywhere. This way the database library will always be available. The other option would be to load it using $this->load->database() only when we need it.

Anyway, going back to the get method. We are using a $id parameter with a default value of false. It allows us to use the same method to get one specific entry (in case you set the $id) or many entries (in case you don’t set any parameter). This is done in the first line of the method, using a IF statement and the method $this->db->where(), which sets a where condition in our query.

Next, we set the ORDER BY to use the email and finally we run the query using $this->db->get() method. In order to return the proper results, we use the $get->row_array() in case the $id was set (it means we have only one result, so we want only the array of that specific entry). In case the $id was not set and the number of results in higher than zero, we will return an array of entries, no matter how many. If the query didn’t return anything, we will return an empty array.

public function create($data)
$data['password'] = sha1($data['password'].$this->salt);
return $this->db->insert('user', $data);

The create method inserts the user info into the database. In the first line we are using the PHP function SHA1 to encrypt the user’s password, concatenated with the “salt” (the first property we set in our class). After that we return the result of the insertion (it will be false in case an error happens or the ID of the user if everything goes as planned).


Before you start, don’t forget to remove the welcome.php file. Create the install.php file in the application/controllers folder and add the following content:

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

class Install extends CI_Controller {

This is the class that contains our controller methods. It will be accessed with the URL http://localhost/task_board_tutorial/install. We need two methods inside it, one that loads the view in which we can input the information and another one to create the user in the database.

    public function index()
        $data = array();

        // Check if users are already there
        $users = $this->user_model->get();
            $data['already_installed'] = true;
        } else {
            $data['already_installed'] = false;

        // Load View
        $data['page_title']  = "Installation";

        $data['email'] = '';
        $data['password'] = '';

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

The index() method is called by default when you access this controller. It will check if there are users in the database in order to know if the installation should proceed or not. This is done using the user model we created before, using the get() method. With that information we set the ‘already_installed’ variable which will be verified inside our view. Next we define other variables used inside the view and load it using $this->load->view().

    public function run()
        // Check if users are already there
        $users = $this->user_model->get();
            $insert = array(
                'email' => $this->input->post('email'),
                'password' => $this->input->post('password'),
                'level' => $this->user_model->USER_LEVEL_ADMIN

        // Load View
        $data['page_title']  = "Login";

        $data['email'] = '';
        $data['password'] = '';

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

This method is executed via post by the form inside the login view (that we will create next). It checks once again if there are already users in the database. In case the database is empty (the $users variable is false), an array with the user information is created using the post variable (in CI we use $this->input->post()) and passed as a parameter to the create method of our model.

The same view is loaded once again, but this time it will open the login form (they look exactly the same, but their actions are different). Let’s finish this section with the view.


Before creating this file, remove the welcome_message.php file. We won’t need it. Now go on and create login.php inside the application/views folder. This is a simple file, so I’m going to paste everything at once.

<div class="home-title blue-gradient">Simple Task Board</div>
<div id="login">
    <?php if(isset($already_installed) && $already_installed) { ?>
    Simple Task Board has already been installed.
    <?php } else { ?>
        <?php if(isset($already_installed) && !$already_installed) { echo form_open('install/run'); }
        else { echo form_open('login/validate'); } ?>

        <?php echo form_label('Email', 'email'); ?>
        <?php echo form_input('email', $email); ?>
        <?php echo form_label('Password', 'password'); ?>
        <?php echo form_password('password', $password); ?>

        <?php if(isset($error) && $error) { ?>
        <p class="error">That's not right! Please check your information and try again.</p>
        <?php } ?>

        <?php if(isset($already_installed) && !$already_installed) { echo form_submit('install', 'Install', 'class="btn-blue"'); }
        else { echo form_submit('login', 'Login', 'class="btn-blue"'); } ?>

        <?php echo form_close(); ?>
    <?php } ?>

I’m not going to explain the entire HTML, just the main parts. This view is just a login form with email and password information. But there are a few validations inside it. First we check for the $already_installed variable (remember we defined it inside the install controller – index() method). If it is set to true, it will show a message informing the app has already been installed.

In case it was not set, or it was set to false, it will show the form using form_open(). But there is a difference between not being set and being false. Remember that in the run() method of the controller we didn’t define it? That’s because it will open the form with the action ‘login/validate’. In case it is defined but false, it will open the form with the action ‘install/run’. Those actions will execute different things when the submit is pressed:

  • ‘login/validate’: executes the method validate() inside the login controller (which will be created next week)
  • ‘install/run’: executes the method run() inside the install controller (previously defined)

With this logic we can use the same view for different purposes, installation and login. i’m doing it this way because I’m the only one working in this project, so it is easier for me. If you work in a team, with designers that are not familiar with coding, I would recommend that you separate this view in two, removing the logic from the views and adding it into the controller. This makes it simpler to style different things and to understand what is happening in the view.

Before we test our app we need something else. Because we used the form functions, we need to load the form helper. This will be done once again in the autoload file. Open config/autoload.php and in the helper section, set the following:

$autoload['helper'] = array('form');

Now, if you go to http://localhost/task_board_tutorial/install, this is what you will see:

Task Board Tutorial - Install

If you check the source code you will note that we have not head or body tags. That’s because we didn’t put them in our view. Why I did that? Because next week I’ll show a simple template library that will load the header and footer for us. This will keep our views clean and will help us when we need to update something like a CSS or JavaScript, because we will do it in one place.


In this post we saw a little bit of how this thing is going to work. CI is a helpful tool and I hope you will be able to see that with these tutorials. Next week I’ll show you the template library that I created and the login screen, which will lead us back to the view we created today. We will create some CSS for that as well. Please leave your thoughts in the comments.

  • When I run this http://localhost/codeigniter/install the browsers says:

    Not Found

    The requested URL /codeigniter/install was not found on this server.

    Apache/2.2.22 (Ubuntu) Server at localhost Port 80


  • Hi,
    I tried few time, but I am getting:
    404 Page Not Found

    The page you requested was not found.

    I checked everything was there!!

    • Have you used the http://domain/task-board/install URL? In this part of the tutorial we haven’t created the controller login.php, which is our default controller in the routes definition. So if you try to go to http://domain/task-board/ it’s going to give you a 404. In the next part of the tutorial we will create the login.php controller.

  • Fahad

    I have a problem accessing the controllers other than default when i use these settings in .htaccess
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ /task_board_tutorial/index.php/$1 [L]

    but when i used these problem was solved but i was still unable to include css on all pages and links were not working in the menu it appends then previous links.

    # Turn on URL rewriting
    RewriteEngine On

    # If your website begins from a folder e.g localhost/my_project then
    # you have to change it to: RewriteBase /my_project/
    # If your site begins from the root e.g. example.local/ then
    # let it as it is
    # RewriteBase /eduweb/

    # Protect application and system files from being viewed when the index.php is missing
    RewriteCond $1 ^(application|system|private|logs)

    # Rewrite to index.php/access_denied/URL
    RewriteRule ^(.*)$ index.php/access_denied/$1 [PT,L]

    # Allow these directories and files to be displayed directly:
    RewriteCond $1 ^(index\.php|robots\.txt|opensearch\.xml|favicon\.ico|assets|forums|css|css/admin.css|images)

    # No rewriting
    #RewriteRule ^(.*)$ – [PT,L]

    # Rewrite to index.php/URL
    RewriteRule ^(.*)$ index.php/$1 [PT,L]

    • If you use the simple .htaccess with the correct path than the problem should be the base_url. The CSS and all links are based on the base_url.

  • Maqsood Elahi

    Dear Oscar Dias,
    I am reading your series of tutorial on codeIgniter for the second time. Very good and helpful for the beginner like me. I really enjoyed it but I think it the series has some catches in it. I got some insight in the library but have not been able to see the dashboard you created. Dear ‘virtue is its own reward’, when you give your ‘fruits’ to other to help them, why insert catches in it? The developers like you are geeks, pears or leaders for amateurs and non professional persons.I appreciate your generosity and hope to have a ‘ turn key’ copy of the series. I am an old man; Do not mind my english or language. Best of wishes for you deeeeeeeeeeear.

    • Hi Maqsood,

      The idea was not to insert any catches in it… but the problem is that I don’t have enough time to write, which means that sometimes I miss something. If you have any question let me know and I’ll try to help you out.

  • Dave

    Hi I am trying to install direct from github. I get the following error. is this to do with my mod_rewrite?

    A Database Error Occurred
    Error Number: 1146

    Table ‘task_board.ci_sessions’ doesn’t exist

    INSERT INTO `ci_sessions` (`session_id`, `ip_address`, `user_agent`, `last_activity`, `user_data`) VALUES (‘2cf5299a9095b75f468708acdaf67945’, ‘’, ‘Mozilla/5.0 (X11; CrOS x86_64 4920.44.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.59 Safari/537.36’, 1387096947, ”)

    Filename: libraries/Session.php

    Line Number: 328

    • Dave

      ok so mod_rewrite is fine. Install still was not working so I used your sql code to create the tables. This got me through to the login screen and let me log in. I am now on the dashboard page but I get the error

      A Database Error Occurred
      Error Number: 1146

      Table ‘task_board.project’ doesn’t exist

      • Dave

        Another update, sorry. I didnt realise your github stuff was a different version to this. I used your download on page 4 and everything is working fine – although you cant add any tasks. It seems that somewhere along the way I need to create a task_board.project table thats not covered in this tutorial

        • Hi Dave,

          If your’re installing from the GitHub version you should run the database script AND run the database upgrade from the app itself. I’ve been out of time, but I need to move this database queries inside the migration to make things easier.

          But the GitHub version has moved far from the tutorial by now…

          • Dave

            Thanks. I am getting there especially now that I realise that your blog goes to six parts (i thought it stopped at 4 which was really confusing – sorry). I have got everything running now but one thing I would like to do with this allow people to sign up and create their own dashboard and then share it. I know this is well beyond the scope of your tutorial but can you give me some idea of what I should be searching the internet for – I lack the terminology to search for this properly. Thanks so much for making all this hard work open!!

  • Arshad Iqbal

    Hi Sir.

    I went through part-2 tutorial. But when i tried to run it using “localhost/cit/install” it is showing me error..
    “Unable to load the requested file: helpers/from_helper.php”

    It tried to find the solution for it, but i couldn’t get any help.
    Please help me..

  • Arshad Iqbal

    I am sorry.
    instead of “form” i had made it “from”.
    got this problem solved..

  • anand sharma

    sir can you share source code for the same sample task board