This is lesson nine of a 10 ten-lesson course, Simple CodeIgniter App, which walks you through the creation of your first PHP web application using the CodeIgniter framework.
In the previous lesson, we set up our Todos
controller and established its index
action, which will power the page that will display our todos. Within that action, we used our Todo_model
to retrieve the todos from our database, and told it to load our view, passing it our todos’ information.
In fact, we did everything except establish the index
view, itself, in order to actually display the todos and complete the MVC loop (pictured below). That’s where we pick up this week.
(Note: If you established the view file on your own in completing last week’s exercise, nice work! It’s explained below in the “Creating a view” section, but you, of course, won’t have to create it again. Just keep following along.)
Passing data to our view
You’ll recall that the last line of the index
view in our Todos
controller is:
$this->load->view('todos/index', $data);
Up to now, we previously only called load->view
passing it one parameter — the name of the view — such as in the Welcome
controller’s index
action, for example:
$this->load->view('welcome_message');
The main difference to note here, in the case of our todos index
action, is that we’re passing the load->view
function a second parameter: our $data
array. This is the magical step that will allow us to access all of the data contained within our $data
array within our view file.
This is demonstrated in the figure below. When items are added to the array being passed to the view ($data
, in our case), they’re made available in the view via variables with names that correspond to their keys in the array.
Now there’s only one problem…the view that we’re telling our controller to load doesn’t exist yet! Let’s create it.
Creating a view
We’re almost there! In terms of retrieving our necessary data, organizing it properly, and making it available to our designated view, we’re all set. Now we just need to create the actual view in order to render our data.
The new Todos index
view
Again, as we saw previously, we’re loading our view with the following line:
$this->load->view('todos/index', $data);
That means that our view should live at the following location: application/views/todos/index.php
.
Go ahead and create the new todos
folder within application/views
and then create the new view file, index.php
, within that folder, with the code shown here:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Simple CodeIgniter App - Todos</title>
<link rel="stylesheet"
href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h1>Todos</h1>
<p>More data coming soon…</p>
</div><!-- /.container -->
</body>
</html>
This is just a simple HTML page structure, which, at the moment, only includes a heading and some placeholder text.
You’ll also notice that we’re including the Bootstrap framework, which will provide us with some built-in CSS for styling our page’s elements.
You won’t be able to see any information about our todos just yet (that’s our next step), but you should now be able to access the new view, via its automatically-generated route — the URL corresponding to a controller and one of its actions — at http://localhost/todos-app/index.php/todos/index.
When visiting the URL above, you should see an extremely simple page similar to the one shown below.
CodeIgniter’s automatically-generated routes
Remember that CI’s automatically-generated routes take the following form:
index.php/<controller-name>/<action-name>
Also remember that, when visiting a URL associated with the
index
action of a controller, you can omit index from the URL, so the following URL will display the same page:http://localhost/todos-app/index.php/todos
Accessing the data passed to our view
When we constructed our Todos
controller’s index
action earlier, we created a $data
array—which contained an array of our todos—and passed it to the view-loading function. The question now is: how do we access that data from within our view?
Back in the action’s code, we added our array of todos to the $data
array like so:
$data['todos'] = $all_todos;
As we discussed previously, that allows us to access our todos array from within our view file using the variable $todos
, whose name corresponds with the key, 'todos'
used when adding the todos to the $data
array, as demonstrated in the figure we saw above, previously.
Go ahead and replace the placeholder content in our index
view with the code shown here:
.
.
.
<h1>Todos</h1>
<div class="list-group">
<?php foreach ($todos as $todo) { ?>
<div class="list-group-item clearfix">
<?php echo $todo->task; ?>
</div>
<?php } ?>
</div>
.
.
.
Since our views are PHP files—notice how they end in .php
—we’re allowed to use PHP code directly within them.
Generating the list of todos
To display our todos, we’re using a few div
elements, along with some of Bootstrap’s built-in styling—list groups, in this case. The list group classes allow us to present a list of items in a simple, yet elegant, manner.
For now, we’re just creating a list of our todos’ task texts. As you can see in the code above, we’re using a combination of HTML and PHP in order to render the list.
Since we need to generate one list item for each todo, it’s the perfect time use a … you guessed it … foreach
loop, which we discussed back lesson 4 on core coding concepts.
Our foreach loop above loops through each of our todos in the $todos
array, and inside the loop, generates a list item for each, printing the todo’s task inside:
<?php foreach ($todos as $todo) { ?>
<div class="list-group-item clearfix">
<?php echo $todo->task; ?>
</div>
<?php } ?>
Now, if you refresh our todos index page — http://localhost/todos-app/index.php/todos — you should see a list of our todos, as shown in the figure below. Success!
You should recognize the familiar echo
function in the code above, which simply prints out a designated string—the todo’s task, in our case. What may look a little unfamiliar in all of this though is the ->
syntax used to access the todo’s task:
$todo->task
In order to understand why that’s the case, let’s take a step back and discuss how CodeIgniter (CI) represents items that are retrieved from our database.
How items retrieved from our database are represented
When you retrieve items from the database, CI is smart enough to automatically represent all of those items’ data as class objects. As we discussed back in lesson 5, class objects can be used to represent data objects. And class objects have properties that can be accessed using the arrow, ->
, syntax.
As shown in the figure below, when you retrieve items from the database, all of their information can be accessed according to the database column names. So if we were to retrieve a todo and store it in the $todo
variable, we could access its task text using:
$todo->task
Accessing class object’s data/properties
When access a class object’s properties, use the arrow syntax, such as:
$object->property
.
And that’s exactly how we’re accessing our todos’ tasks in our index
view. As mentioned, we can access any of the data retrieved from the database.
Understanding the full loop
We covered a whole lot of new ground in these previous two lessons.
Well, let’s rephrase that: we did cover some new ground, but more so, we pieced together a lot of previous knowledge to accomplish a bunch of new things.
You knew about the four essential pieces to the full loop—the database, model, controller, and view—but we had yet to put them all together to get real results.
You have now built the foundational basis for every web app in existence: a way for a user to access a URL and be presented with real data.
As always, apps can grow to become more and more complex, but that mainly happens by iterating on the process we’ve walked through thus far:
- Establish the necessary database tables to store your items’ data
- Create a model to help represent those items within the app and retrieve their information from the database
- Create a controller to establish connections between URLs and the app’s desired functionality
- Create views to display designated pieces of information to users
When it comes down to it, this process is one of the most fundamental in all of web development.
Give yourself a huge pat on the back for making it this far. You now have a strong understanding of the core of a true web application.
Week 9 Task
Prepare the app for the todos completion functionality
The final big piece of functionality we’ll be adding to the app is the ability to mark todos as “completed”. In this week’s task, we’re going to prepare our app’s code so that we’re ready to implement the full completion functionality next week.
1. Autoload CI’s form library
Remember back in lesson 7 when we autoloaded the database library to make it available throughout our app? Well, now we need to autoload CI’s form helper so we can access its form functionality in our views.
Open the autoload config file — application/config/autoload.php
— and add a 'form'
entry to the $autoload['helper']
configuration array in order to accomplish this.
2. Add checkboxes to the todo list items
We’ll be using checkboxes in order to designate whether or not a todo item has been completed.
Referencing CI’s Form Helper documentation, add code to our index
view that creates a checkbox before each todo’s task text.
You should use 'completed'
for the checkbox’s “name”, the $todo
item’s id
for the checkbox’s “value”, and the $todo
item’s completed
status to designate whether or not the checkbox is checked. (Note: Remember, in order to reference pieces of information about a todo — such as its id or completed values — use the arrow, ->
, syntax.)
After you’ve added the code to display the checkboxes, use phpMyAdmin to manually change the completed values of a few of the todos in your database, and make sure that the checkboxes on your page are checked/unchecked accordingly.
And by now, you know the drill — if you have any questions, feel free to shoot me an email or leave a comment below and ask away.
Next week, we’ll wrap everything up and finish our app!