Getting Started With CodeIgniter: Part 2 - MVC
Welcome back. In the last section we got up and running with CodeIgniter and familiarized ourselves with the structure and installation of it. This time, we're going to take a closer look at how CodeIgniter handles MVC, and what MVC really even means!
This is the meat of CodeIgniter and most other web application frameworks (Symfony, Zend, CakePHP, and even the infamous Ruby on Rails). It's also a really great way to structure any kind of application, and you'll feel like a better person for having learned it. And it's good in bed. Moving on...
Crash Course In Object Oriented PHP
CodeIgniter just isn't going to make sense unless you familiarize yourself with a the basic concepts of object oriented programming. The typical programming style of many PHP coders involves coding in a linear fashion (do this then this then this or that). This is fine for small (I mean like itty bitty small) projects, but as an app becomes larger, this gets confusing, ugly, and just plain bad.
In contrast, we have Object Oriented programming. CI (and MVC in general, we'll get to that later), uses a pretty simplified version of OOP. At the most basic level, we have classes, objects, and methods/functions. Classes are a general blueprint or structure of something. A good example of a class is a dog. A dog has four legs, is furry, can bark, etc. A dog is a class.
Next we have objects. Objects are specific instances of classes. For example, if "dog" is a class, then my dog Australian Cattle Dog named "Tuck" would be an object. It's a specific member of a class.
Finally, we have methods or functions. These are things which member of the class can do. For example, the dog class has a bark() function, a jump() function, an isSleeping() function, etc. In the programming world, you have to create a new object (or instance of a class), usually (depending on the language) using something like var sparky = new Dog();, and then you can call methods on our dog. In PHP, calling functions on an object uses the arrow syntax, so to make Sparky jump, we'd use sparky->jump();.
This is a REALLY simplified version and Wikipedia's definition of Object Oriented programming might help if you're still confused. However, it's pretty important to have a basic understanding of this, because CI depends on it, as we will see.
Models, Views, Controllers, Oh My!
CodeIgniter is founded upon the tried and true MVC philosophy. Basically, the whole point of MVC is that you separate what the user sees (i.e., the views) from all the back end stuff (usually in the models). The back end and the front end are the connected using controllers.
Now do NOT freak out! This is much more simple than it sounds. And once you get going, I promise that you will never want to go back. This separation makes everything simpler, easier to understand, and some might say more beautiful (though I'd prefer not to geek out like that, so I'm not going to). Here's a basic rundown of the tasks of each of these three components.
NOTE: You're going to see a lot of talk about naming conventions. Naming conventions are not absolutely necessary in CI (as they tend to be in CakePHP) but they are recommended just because if you always follow the same guidelines, you won't have to spend time trying to remember what something was called. I try and follow the naming convents recommended by EllisLabs, the makers of CodeIgniter, although you can develop your own and stick to that.
Models
Models usually do anything having to do with connecting to a database and performing CRUD (Create, Read, Update, Delete) operations. I like to have one model for each table in my database, usually named "tablename_model.php". Models (and controllers) contain a constructor, often with the same name as the page except uppercased (so if your page is named blog_model.php, your constructor should be named Blog_model).
Remembering back on our discussion of Object Oriented programming, a model would be a "class". Each model has its own functions (remember that?) which can be called after you create a specific instance of the model. Calm down. Here's an example.
Say you've got an eCommerce site, so you probably have a database with tables like products, users, orders, etc. So to build a model for the products table, you'd create a products_model.php document, and structure it like this:
-
<?php
-
class Products_model extends Model {
-
-
function Products_model()
-
{
-
// Call the Model constructor
-
parent::Model();
-
}
-
-
function something1()
-
{
-
.....do something....
-
}
-
-
function something2()
-
{
-
.....do something else....
-
}
-
}
-
?>
So basically, you've got a model with the same name as the php page's name, and the first function called is the constructor, which as the same name as the model. The constructor then tells CI that it's parent is the generic model class. After that, you stick in a few functions which relate to the database and products. You might have a getPrice() function or a deleteProduct() function. These functions create a little mini library of things which your controller can work with, but the controller itself doesn't ever have to worry about how they're being done. We fancy programmer types like to call this "abstraction." Oohhhhh.....
It's worth saying that CI doesn't REQUIRE that you use models at all. You could put all of the database interaction right in the controller if you wanted. Just do yourself a favor and use them. As your application grows, you'll be glad that you have the extra layer of separation to keep yourself sane.
Controllers
Controllers are the bridges between the back end and the front end. In the previous eCommerce example, the Products_model had functions which performed all of our CRUD operations for us, and our controller will call those functions to do whatever it needs to do, and then output whatever it needs to display to a view. In my opinion, controllers are the beauty of MVC frameworks like CI. You have the database stuff in a model, the front-end stuff in a view, and then everything between in a controller. It's the middle man. Doesn't it just make you all tingly? That's just me? Don't lie.
The anatomy of a controller is a lot like the model. Your controller's name will be all lowercase, and should explain whatever it is dealing with. For example, we would probably make a products.php controller to communicate between our products_model.php and our views. We'll call it products.php, and it will look something like this:
-
<?php
-
class Products extends Controller {
-
function Products()
-
{
-
parent::Controller();
-
}
-
function index()
-
{
-
echo 'Hello World!';
-
}
-
}
-
?>
NOTE: Functions in controllers are really cool in CI. Instead of having a separate php page for each page in your site, you can have a separate controller for each section, and pages within that section get their own function in the controller. That means that by default, when you navigate to a controller (such as www.yoursite.com/index.php/products), the index function of the products controller is called. However, if you want to have a page that displays all the shoes or something like that, you would create a function "shoes()", and then navigate to www.yoursite.com/index.php/products/shoes to execute that function. That's awesome.
But that was a really simple controller. More often, a controller will create a new instance of a model, do some functions from the model, and then pass the results to a view to display them on the browser. It will look something like this:
-
<?php
-
class Products extends Controller {
-
{
-
$this->load->model('Products_model');
-
$data['price'] = $this->Products_model->getProductPrice(some_parameter);
-
$this->load->view('products_view', $data);
-
}
-
}
-
?>
Get VERY used to the syntax of the load statements ($this->load->something_or_other). Your controller uses this statement to create a new instance of a model or to pass data to a view to be displayed on the browser. In this case, we tell CI that we are going to be talking to the Products_model using the load statment. Then, we call the getProductPrice() function of the Products_model and pass the results into an associative array named $data. We will call our result 'price', so it gets put into $data['price'].
This $data array is very important because it is what we use to give information to our view. Speaking of views...
Views
Views display everything that the user sees. There are endless ways you can set up views. Some applications may be small enough that you can only have one view, and have it represent different pages based on the different information that controllers pass to it. You could also have a completely different view for each page. It's up to you, and it depends on how complex your pages will be.
Views obviously go inside the views folder, and I usually name them something_view.php. If your view is meant to display a list of products, why not name it products_view.php. Notice that models are named something_model.php and views are named something_view.php while controllers are just named something.php. This is because the name of the controller is what shows up in the URL, and you want to keep that pretty. Yes, I know, you can change what shows up in the URL to pretty much whatever you want to in routes.php, but since we're sticking to the basics, I'll try not to confuse you with all of that.
Basically, a view is a lot like a regular HTML page that we're all familiar with, complete with a Doctype, head and body tags, etc. In fact, it's really common to have a header view and a footer view to load before and after whatever content view you're using.
This is the cool part: The view outputs information passed to it by the controller. Anything inside the $data array (in our controller example's case, the 'price') will be passed to the view, and we can reference that using the name of the object as a variable. This is not as confusing as it sounds! Say we pass $data['price'] to the view. In the view, we can reference that using $price. If we passed $data['description'], we could reference it in the view using $description. This is the beauty of it all. We can even make the $data array contain other arrays. Say the $data array contains an array called 'productinfo'. In the view, we could do stuff with $productinfo['price'] or $productinfo['shipping'] or all kinds of stuff. Endless opportunities! HOORAY! You may not be as excited as I am, but you will once you get going with it all.
To demonstrate, here's a really simple view that echoes the price we passed to it:
-
<html>
-
<head>
-
<title>My Store</title>
-
</head>
-
<body>
-
<h1>The price is:<?=$price?></h1>
-
</body>
-
</html>
Nice and simple. Notice the alternative PHP syntax. Instead of using an echo statement to send out the price, just use...
-
<?=$something_to_echo?>
...and the "=" does it for you. Just a little shortcut. Although, as cheekygeek pointed out in the comments below, this does require that short tags are enabled in php.ini. If it doesn't work for you, that's probably why. However, in system/application/config.php at the bottom, you can change $config['rewrite_short_tags'] = TRUE; and CodeIgniter will rewrite all of them on the fly so they will still work with your server.
Well that's it for this time. Hope you learned something, and be sure and check back for part three coming soon! Happy coding!











June 21st, 2008 at 12:16 pm
CI newbie here again:
You jump right into explaining models, which is great, but I’ve noticed that models are often explained as “optional”. The official CodeIgniter blog screencast tutorial, for instance uses controllers and views, but not models. I think it would be helpful (conceptually) to see something done with JUST controllers and views AND THEN doing the same thing by also utilizing a model. I think this might make clearer the proper roles of the two (controllers vs models) and better illustrate the benefits of using models.
Good idea or not?
These are super tutorials and should be required reading for newbies. (I had to utilize the “calm down” part a lot last night when even the simplest things were resulting in blank pages.)
By the way, are you a Mac user?
June 21st, 2008 at 12:27 pm
PS… the short tag thing you mention at the end. Doesn’t that require you to enable short tags in your php.ini file? Or does CodeIgniter somehow understand short tags even if it is OFF in the php.ini?
June 21st, 2008 at 3:20 pm
@cheekygeek
You’re right, short tags still must be enabled in php.ini. I made a note of it in the post.
Thanks for the idea about doing something using just controllers and views and then doing the same thing using models, as well. I was considering doing an in-depth example as part 6, and that would work pretty well!
I’m actually a geeked out linux user. I code on a localhost LAMP server, edit server pages with SSH, etc. Don’t hate
June 21st, 2008 at 4:23 pm
Linux is cool. I reserve my hate for only the truly vile. (ie: Windows)
And people who use emoticons.
June 21st, 2008 at 4:30 pm
The above comment is not as funny when the blog strips emoticons from comments.
June 28th, 2008 at 2:23 pm
The BEST tutorial (I’d rather say crash course) on codeigniter I have ever seen. I didn’t know what to do with MODELS until I read this. Keep it up! Superb!!
July 3rd, 2008 at 1:06 am
Agreed. THE BEST tutorial I’ve ever read. You can easily write a book or become a professor or something..:)
July 3rd, 2008 at 6:08 am
Hi. On downloading the latest version of Codigniter, I noticed that the closing php tags have been omitted from php files! I first thought that this must be some sort of error. However, according to the docs, codigniter recommends leaving php closing tags off ALL php files!!! Any thoughts?
July 3rd, 2008 at 7:00 am
@all - Thanks for the kind words! They’re much appreciated.
@Mikw - The docs recommend leaving out closing tags simply because you don’t need them (PHP will auto close all PHP files without the end tag) and because if you DO close them and then include ANY whitespace (i.e., a space, a new line, anything), then PHP tries to output that whitespace to the browser which often causes header errors. Therefore, you can leave the closing tag off and you don’t have to worry about it.
However, I usually include closing tags just because I’m a freak for structured code and it makes me happy. You can leave them off if you’d like.
October 11th, 2008 at 11:47 am
Why don’t u start tutorials on Jquery too? It will be very helpful as the way u present is very simple yet gr8!!
October 17th, 2008 at 10:17 pm
well … i cant say more than above …
excellent tutorial … I have read many many computer books in life … but your honesty in writing can be felt on what you’ve posted. its amazing.
I learned MVC from J2EE … it took me more than a month just to get the idea … let alone to code it …
some writers try to make simple things simpler … but they end up making it complex to understand …
i’ll for sure finish reading this whole series …
Thank you very much for making life easier to many …
October 18th, 2008 at 7:07 am
Thanks a lot guys! Glad you enjoyed it.
November 25th, 2008 at 4:40 am
Hey thanks again Mike - Great job of helping us “newbies” understand how CI works. Its the basic concepts we have to get straight…Once you figure it all out the rest will become trivial.
@Praveen: As for the jquery tutorials that you mentioned there are a bunch of them out there. You can start here: http://www.learningjquery.com
I think Mike has done a great job with understanding what people need to learn VS whats already out there. In my limited knowledge dont fight battles that are already won!!
Great job Mike, hats off to ya!!!
November 26th, 2008 at 5:36 pm
Thank You! TY! TY!!! I have been pulling out what is left of my hair for the last week or so trying to figure out why I could only view the HTML portion of the web site I’ve been updating which was designed using CI. Any of the code that was getting called in what I now know are “short tags” was never working. I read your guide and finally have it working on my laptop!
November 26th, 2008 at 6:09 pm
@Dwayne
Glad I (and cheekygeek) could help! Now that you’ve got it working, enjoy! Now comes the fun part.
December 13th, 2008 at 5:53 pm
You have a gift for making complex information simple and FUN to read. This has been the best bit of tutorial writing I have ever read, so thank you for your hard work in preparing the material. And yes, I am very excited to read the rest of the tutorials and dive in to Code Igniter. Thanks for ‘igniting’ my passion for learning CI! Cheers,
Dan
December 14th, 2008 at 10:01 am
@Dan
Wow, thanks for the kind words! Glad I could help!
December 28th, 2008 at 3:50 pm
You really do have a gift for taking complex concepts and making them easy to understand. Clear and straightforward writing (not to mention funny, too). Thanks for putting these tutorials together.