Developing dynamic Web sites with CodeIgniter

Use the MVC framework with CRUD for efficiency

Learn how to quickly and efficiently code a dynamic Web site using CodeIgniter. By leveraging CodeIgniter’s framework and built-in shortcuts, you will write the necessary MVC files to create, read, update, and delete (CRUD) items to and from a database.

Kevin Howard Goldberg (kgoldberg@imagistic.com), CTO, imagistic

Kevin Howard GoldbegWith 20 years of experience in the high-tech industry, Kevin Howard Goldberg is a technology executive, author, and consultant residing in Westlake Village, Calif. He currently serves as CTO at imagistic, an award-winning digital marketing and technology company, which he co-founded in 1997. An expert on Web development and technology, he serves on the Santa Monica College Computer Science Advisory Board and held senior positions at Film Roman, Lionsgate, and Philips Interactive Media. He is the author of XML: Visual QuickStart Guide (2nd Edition), (PeachPit Press, 2008). You can reach him at http://kehogo.com/contact.



12 January 2010

Also available in Japanese Portuguese

CodeIgniter is an open source Web application framework written in PHP. It can work with many database applications, including MySQL, DB2® Express-C, and others. The framework uses the MVC design pattern, the primary goal of which is to separate the data and presentation layers of a software application. In the Model-View-Controller (MVC) pattern, the model manages the data layer, communicating with the database; the view manages the presentation layer, displaying the UI and content; and the controller manages the communication between the views and models.

Frequently used acronyms

  • CRUD: Create, Read, Update, Delete
  • HTML: Hypertext Markup Language
  • MVC: Model-View-Controller
  • SQL: Structured Query Language
  • UI: User interface

This article outlines the steps necessary to create the foundation of a dynamic Web site or application using CodeIgniter. It assumes that you have CodeIgniter V1.7.2 or later and MySQL V4.1 or later installed, and that you have a basic familiarity with both. If you're new to CodeIgniter or need a quick refresher, see Resources.

Site foundations: Widgets and CRUD

Of course, most dynamic Web sites are going to be different from the example used in this article — in most cases, significantly different. However, all dynamic Web sites have two critical things in common: a database and something retrieved (dynamically) from that database. For the purpose of generalizing this discussion, I call this dynamically retrieved something a widget. A widget could be pretty much anything — a book for sale, a recipe, a blog entry, or a press release. Regardless of what the widget is, its definition requires a consistent set of information. For example, the set of information needed for a recipe might include a title, ingredients, instructions, and a nutritional breakdown.

To retrieve the widget from the database, you must first create it (then it might be updated or even deleted). That's where CRUD comes in. CRUD represents the four primary operations needed to manage widgets in a database; together with the widget itself, they are the foundation of any dynamic Web site.


Setting up the database

For this article, you'll create a Web application to manage the contact information for a group of students and their parents, such as a kids' sports team, a YMCA group, or a school class, which is the example you'll be creating.

To begin, create the data model for the widget. The set of information needed for this widget is:

  • Student's name
  • Parents' names
  • Address
  • City
  • State
  • ZIP or postal code
  • Phone number
  • E-mail address

To store this widget, create a table called student with fields corresponding to the set of information identified in the list above. A MySQL database and table-creation script is shown in Listing 1.

Listing 1. MySQL database and table-creation script
CREATE DATABASE classroom;

USE classroom;

CREATE TABLE IF NOT EXISTS `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `s_name` varchar(64) DEFAULT NULL,
  `p_name` varchar(64) DEFAULT NULL,
  `address` varchar(128) DEFAULT NULL,
  `city` varchar(32) DEFAULT NULL,
  `state` char(2) DEFAULT NULL,
  `zip` char(10) DEFAULT NULL,
  `phone` char(20) DEFAULT NULL,
  `email` varchar(64) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

Initial CodeIgniter setup

After you have created the database and table, set the CodeIgniter database variables in .\system\application\config\database.php and base URL in .\system\application\config\config.php. For the purpose of this article, I assume that the base URL is http://127.0.0.1/codeigniter/.

A default controller and view

Next, create a default controller and view. (When these are in place, you'll be able to see the effects of any code you write.) For this project, create a controller called student.php in the .\system\application\controllers\ folder, as shown in Listing 2 and set it as the default controller in .\system\application\config\routes.php.

Listing 2. The default controller: Student
<?php

class Student extends Controller {

  function Student()
  {
    parent::Controller();  
  }
  
  function index()
  {
    // display information for the view
    $data['title'] = "Classroom: Home Page";
    $data['headline'] = "Welcome to the Classroom Management System";
    $data['include'] = 'student_index';

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

/* End of file student.php */
/* Location: ./system/application/controllers/student.php */

Notice that the index() function creates an array called data that contains three named indices: title, headline, and include. This array is passed to a view named template stored as template.php (see Listing 3) in the .\system\application\views\ folder.

Listing 3. The default view: template.php
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />

<title><?php echo $title;?></title>
</head>
<body>

<h1><?php echo $headline;?></h1>

<?php $this->load->view($include);?>

</body>
</html>

This view will be the HTML shell or visual wrapper for all pages in the Web site. It contains a standard HTML setup and expects three values from the controller —title, headline, and include— which correspond to the page title, page headline, and a view file to include for content display, respectively.

This included view file is the last step of the initial setup. Name it student_index.php, as declared in template.php (Listing 2 above), and stored it in the .\system\application\views\ folder. Listing 4 provides its source code.

Listing 4. Some basic "Hello World" text
<p>Congratulations. Your initial setup is complete!</p>

Notice that there are no standard HTML structure tags. This is because student_index.php is included through the template.php view and is, therefore, part of that view's HTML wrapper and display.

Now, if you navigate to http://127.0.0.1/codeigniter/, the browser loads a page with a page title, a welcome headline, and a congratulations message.


The four CRUD operations

Let's look at the Web application in terms of CRUD operations.

Creating widgets

Now that initial setup is complete, you need to write code that manages the widgets. Start with the first of the four CRUD operations: create. This code must save user input as a widget in the database.

Start by creating an HTML form with fields corresponding to the structure of the student table. Create a view file called student_add.php in the .\system\application\views\ folder, shown in Listing 5.

Listing 5. Generating HTML form fields for the create operation
<?php 

echo form_open('student/create');

// an array of the fields in the student table
$field_array = array('s_name','p_name','address','city','state','zip','phone','email');
foreach($field_array as $field)
{
  echo '<p>' . $field;
  echo form_input(array('name' => $field)) . '</p>';
}

// not setting the value attribute omits the submit from the $_POST array
echo form_submit('', 'Add'); 

echo form_close();

?>

There are two things to note about this file. The first is that it uses the form_input() function. This function is part of the CodeIgniter Form Helper and is a quick way to generate the HTML needed for most forms. It takes three arguments: a field name, a field value, and any additional data (such as JavaScript).

CodeIgniter shortcuts

When starting or prototyping a project, I use as many of the built-in "shortcuts" that CodeIgniter offers (such as the HTML Table class and the Form and URL Helper files) to decrease coding and debugging time. Of course, this is at the expense of a more granular control of the layout or look and feel, but in these early stages, function should supersede form.

The second thing to note is that the form_submit() function, which takes the same three arguments, has an empty string for the field name. This prevents the submit field from being part of the form post array. The model uses this array when adding the record to the database; if the submit field were included, the database insert would fail.

Then you need to add a function to the Student controller (Listing 6) to be able see the HTML form.

Listing 6. The add() function for the Student controller
  function add()
  {
    $this->load->helper('form');
    
    // display information for the view
    $data['title'] = "Classroom: Add Student";
    $data['headline'] = "Add a New Student";
    $data['include'] = 'student_add';

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

Notice that this function loads the CodeIgniter Form Helper to be used by the student_add.php view.

Now, if you navigate to http://127.0.0.1/codeigniter/index.php/student/add, the browser loads the HTML form with fields representing a record in the student table. If you submit the form, you'll get an error because you haven't created a function to receive the form's post. To do so, add a create() function to the Student controller, shown in Listing 7.

Listing 7. The create() function for the Student controller
  function create()
  {
    $this->load->helper('url');
    
    $this->load->model('MStudent','',TRUE);
    $this->MStudent->addStudent($_POST);
    redirect('student/add','refresh');
  }

This function, which corresponds to the URL http://127.0.0.1/codeigniter/index.php/student/create, first loads a model called MStudent, which you create in the next step. It then executes the addStudent() function, passing in the post array created on the student_add.php page. Finally, it redirects the user back to the student_add.php page using the redirect() function that is part of the URL Helper file.

The MStudent model is responsible for interacting with the student table in the database. In the .\system\application\models folder, create a file named mstudent.php. (It's good practice to prefix or append the file name with something indicating that the file is a model, thus the m). Its code is shown in Listing 8.

Listing 8. The MStudent model responsible for the data layer
<?php 

class MStudent extends Model{

  // Create student record in database
  function addStudent($data)
  {
    $this->db->insert('student', $data);
  }

}

/* End of file mstudent.php */
/* Location: ./system/application/models/mstudent.php */

This model uses the db->insert() function to insert the post array data into the student table. The function takes two arguments: the name of the table and an associative array of field names and values. This function is part of CodeIgniter's Active Record class, which is automatically loaded, and is one of the shortcuts that CodeIgniter provides to decrease development time.

Also, as noted, if the post array included the Submit button as a field, the insert would fail because there isn't a field in the table called submit.

Navigate again to http://127.0.0.1/codeigniter/index.php/student/add. This time, put some data into the fields and click Submit. The page will refresh, and the fields will be emptied. But if you check the database, you'll see that the data you submitted has been added to the student table.

Retrieving widgets

The second CRUD operation is read: The code simply needs to read widget records from the database. Of course, it's also common to display these records, which is why many people refer to this operation as retrieve, instead.

Begin by updating the MStudent model with a function to retrieve the student table records, as shown in Listing 9.

Listing 9. MStudent function to retrieve student records
  // Retrieve all student records
  function listStudents()
  {
    return $this->db->get('student');
  }

This code uses the db->get() function, also part of CodeIgniter's Active Record class, to generate a SELECT * against the table named in the function's argument (student).

Next, add a function to the Student controller called listing() that loads the MStudent model and executes the listStudents() function, as seen in Listing 10.

Listing 10. Creating the HTML table to display the student records
  function listing()
  {
    $this->load->library('table');
    
    $this->load->model('MStudent','',TRUE);
    $students_qry = $this->MStudent->listStudents();

    // generate HTML table from query results
    $students_table = $this->table->generate($students_qry);
    
    // display information for the view
    $data['title'] = "Classroom: Student Listing";
    $data['headline'] = "Student Listing";
    $data['include'] = 'student_listing';

    $data['data_table'] = $students_table;

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

This function uses the table->generate() function, a CodeIgniter shortcut, in the HTML Table class. It generates an HTML table with field names from the query result object as a header row, then each record listed subsequently. Its result is passed to the template view in the data array.

Finally, you need a view to display this HTML table. Create a file called student_listing.php in the .\system\application\views\ folder, as shown in Listing 11.

Listing 11. Displaying the HTML table
<?php echo $data_table; ?>

To see the results of this operation, go to http://127.0.0.1/codeigniter/index.php/student/listing. You'll see a list of the students retrieved from the database. Now take a moment to add more student records using the input form or run the SQL script shown in Listing 12 to do the same.

Listing 12. SQL script to add student records
INSERT INTO classroom.student 
	(id, s_name, p_name, address, city, state, zip, phone, email) 
	VALUES
(NULL, 'Peter Green', 'Len & Natalie Green', '480 West Broad Street', 
	'Eastbrook Canyon', 'PA', '19104', '(215) 900-2341', 
	'greenery@timewarner.dsl.com'),
(NULL, 'Jonah Ross', 'Robert & Linda Ross', '1293 Law Street', 
	'Eastbrook Village', 'PA', '19105', '(215) 907-1122', 'ross_boss@gmail.com'),
(NULL, 'Rebecca Dillon', 'Lainie and Howard Dillon', '12 Flamingo Drive', 
	'Westbrook Village', 'PA', '19103', '(215) 887-4313', 'ld_1975@yahoo.com'),
(NULL, 'Noah Singer', 'Carolyn & Peter Singer', '393 Green Lake Road, 8th Floor', 
	'Eastbrook Village', 'PA', '19105', '(215) 907-2344', 'candp@gmail.com'),
(NULL, 'Trevor Lee Logan', 'Steven Logan', '400 Green Lake Road, 9th Floor', 
	'Eastbrook Village', 'PA', '19105-6541', '(828) 299-9885', 
	'misterSAL@sbcglobal.net'),
(NULL, 'Audrey Christiansen', 'Lovey Christiansen', '1993 East Sunnyside Lane', 
	'Eastbrook Canyon', 'PA', '19104', '(215) 887-5545', 
	'lovey@christiansen-clan.com');

Before moving on to the next CRUD operation, to make navigating the site easier, add a set of global navigation links above the <h1> tag in to the template.php file in the .\system\application\views folder. This code is shown in Listing 13.

Listing 13. Global navigation links
<div class="navigation">
<?php 
  // nav bar
  echo anchor('student/index', 'Home');
  echo (' | ');
  echo anchor('student/add', 'Add a New Student');
  echo (' | ');
  echo anchor('student/listing', 'List All Students');
?>
</div>

This code uses the anchor() function shortcut, part of CodeIgniter's URL Helper file. And, because every function in the Student controller touches the template view, you need to load the URL Helper as part of the Student constructor (see Listing 14). You should also remove it from the create() function so you don’t load the Helper file twice.

Listing 14. Loading a helper in a constructor
  function __construct()
  {
    parent::Controller();

    // load helpers
    $this->load->helper('url');
  }

Updating widgets

You're now ready for the third CRUD operation: update. For this, the code must:

  • Read one widget record from the database.
  • Display that record for editing.
  • Allow the user to submit the updated information back to the database.

Start by updating the student list to include an Edit option on each row. You can still use the HTML Table class to generate most of the HTML needed for the table. However, you will now need to explicitly loop over the database query result object to create the table rows and add the Edit option. The update to the listing() function in the Student controller is detailed in Listing 15.

Listing 15. Using the HTML Table class to create a table
    // generate HTML table from query results
    $tmpl = array (
      'table_open' => '<table border="0" cellpadding="3" cellspacing="0">',
      'heading_row_start' => '<tr bgcolor="#66cc44">',
      'row_start' => '<tr bgcolor="#dddddd">' 
      );
    $this->table->set_template($tmpl); 
    
    $this->table->set_empty("&nbsp;"); 
  
    $this->table->set_heading('', 'Child Name', 'Parent Name', 'Address', 
        'City', 'State', 'Zip', 'Phone', 'Email');
  
    $table_row = array();
    foreach ($students_qry->result() as $student)
    {
      $table_row = NULL;
      $table_row[] = anchor('student/edit/' . $student->id, 'edit');
      $table_row[] = $student->s_name;
      $table_row[] = $student->p_name;
      $table_row[] = $student->address;
      $table_row[] = $student->city;
      $table_row[] = $student->state;
      $table_row[] = $student->zip;
      $table_row[] = $student->phone;
      $table_row[] = mailto($student->email);

      $this->table->add_row($table_row);
    }    

    $students_table = $this->table->generate();

This updated code takes advantage of the increased granular control of the HTML by:

  • Including a header row with proper field names and a background color.
  • Not displaying the ID field.
  • Adding a background color on alternating rows.

Next, add a function to the Student controller called edit(), which is where the Edit option is pointing. The code is shown in Listing 16.

Listing 16. The edit() function for the Student controller
  function edit()
  {
    $this->load->helper('form');

    $id = $this->uri->segment(3);
    $this->load->model('MStudent','',TRUE);
    $data['row'] = $this->MStudent->getStudent($id)->result();

    // display information for the view
    $data['title'] = "Classroom: Edit Student";
    $data['headline'] = "Edit Student Information";
    $data['include'] = 'student_edit';

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

The Edit option passes the student record ID as the third segment in the URL (after the http://127.0.0.1/codeigniter/index.php/). The uri->segment(3) function (part of CodeIgniter's URL Helper file), parses this ID from the URL and passes it to a function in the MStudent model that retrieves that student record, as shown in Listing 17.

Listing 17. Retrieves a student record from the database
  // Retrieve one student record
  function getStudent($id)
  {
    return $this->db->get_where('student', array('id'=> $id));
  }

Then create an HTML form named student_edit.php to display and edit this student record, as shown in Listing 18.

Listing 18. Create the HTML form view for editing a student
<?php 

echo form_open('student/update');

echo form_hidden('id', $row[0]->id);

// an array of the fields in the student table
$field_array = array('s_name','p_name','address','city','state','zip','phone','email');
foreach($field_array as $field_name)
{
  echo '<p>' . $field_name;
  echo form_input($field_name, $row[0]->$field_name) . '</p>';
}

// not setting the value attribute omits the submit from the $_POST array
echo form_submit('', 'Update'); 

echo form_close();

?>

Notice that this file is nearly identical to student_add.php. Many developers like to use a single add/edit file construct instead of having two distinct files. Ultimately, this is a matter of style, and there are pros and cons to either approach.

Next, to receive the form post, add the function update() to the Student controller; the code is shown in Listing 19.

Listing 19. The update() function for the Student controller
  function update()
  {
    $this->load->model('MStudent','',TRUE);
    $this->MStudent->updateStudent($_POST['id'], $_POST);
    redirect('student/listing','refresh');
  }

Finally, update the MStudent model with a function to update the student record in the database. This function is shown in Listing 20.

Listing 20. Update a student record
  // Update one student record
  function updateStudent($id, $data)
  {
    $this->db->where('id', $id);
    $this->db->update('student', $data); 
  }

The update operation is complete. You can navigate to the student listing, edit any student record, submit the form, and see the updated information in the refreshed student list.

Deleting widgets

The final CRUD operation is delete. In this operation, the user needs to be able to select a record from a list, then delete that record. You also want to confirm the user's intention before actually deleting the record (in case the user clicked the wrong link).

Begin by replacing the code that creates the Edit option in the Student controller listing() function with the code from Listing 21.

Listing 21. Adding the Delete option to the student list
      $table_row[] = '<nobr>' . 
        anchor('student/edit/' . $student->id, 'edit') . ' | ' .
        anchor('student/delete/' . $student->id, 'delete',
          "onClick=\" return confirm('Are you sure you want to '
            + 'delete the record for $student->s_name?')\"") .
        '</nobr>';

Next, add a delete() function to the Student controller, which is where the Delete option is pointing. The code is shown in Listing 22.

Listing 22. The delete() function for the Student controller
  function delete()
  {
    $id = $this->uri->segment(3);
    
    $this->load->model('MStudent','',TRUE);
    $this->MStudent->deleteStudent($id);
    redirect('student/listing','refresh');
  }

Finally, update the MStudent model with a function to delete the record. This function is shown in Listing 23.

Listing 23. Delete a student record
  // Delete one student record
  function deleteStudent($id)
  {
    $this->db->where('id', $id);
    $this->db->delete('student'); 
  }

Now give it a try. Navigate to the student listing and attempt to delete a student record. If you click OK in the JavaScript prompt, the student list will be refreshed and show that the record has been deleted.


Conclusion

Congratulations! You've completed the foundation of a dynamic Web site using CodeIgniter. The Web site has a very clean separation of the presentation and data layers because it uses the MVC pattern. And by including the coding shortcuts that CodeIgniter makes available, development time was expedited, and the lines of code required were minimized. In fact, did you realize that you completed this application using only one controller, one model, and five views? That's pretty efficient coding.


Downloads

DescriptionNameSize
Full code base, including CodeIgniter filesos-codeigniter-classroom.zip2160KB
MVC files onlyos-codeigniter-MVC-files-only.zip5KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Open source on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Open source
ArticleID=460574
ArticleTitle=Developing dynamic Web sites with CodeIgniter
publish-date=01122010