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.

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.

Installation

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:

config.php

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.

database.php

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.

routes.php

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.

Database

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.

user

CREATE TABLE IF NOT EXISTS `user` (
  `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`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 ;

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

ci_sessions

CREATE TABLE IF NOT EXISTS `ci_sessions` (
  `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`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

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.

user_model.php

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


<?php

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

install.php

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
        $this->load->model('user_model');
        $users = $this->user_model->get();
        if($users){
            $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
        $this->load->model('user_model');
        $users = $this->user_model->get();
        if(!$users){
            $insert = array(
                'email' => $this->input->post('email'),
                'password' => $this->input->post('password'),
                'level' => $this->user_model->USER_LEVEL_ADMIN
            );
            $this->user_model->create($insert);
        }

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

login.php

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); ?>
        <br/>
        <?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 } ?>
</div>

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.

Conclusion

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.