This book is about CodeIgniter and the world of Model-View-Controller (MVC) web development. Before venturing into the topic of CodeIgniter, it’s helpful to put it into some kind of context. However, most programmers who are new to the world of MVC web development find some of the concepts hard to grasp at firstthey’ve been so engrained in the old way of doing things that unlearning is difficult at first.
So even before you can learn anything about CodeIgniter or even MVC, it’s probably helpful to start the discussion with something you already know and understand and then move on from there. Therefore, that’s where this book begins: with a description of a prototypical PHP project, most likely very similar to anyone’s very first PHP project.
In addition to the basic CodeIgnitor installation and configuration, you?ll quickly learn how to troubleshoot CodeIgnitor errors. You?ll put CodeIgnitor to work building an ecommerce site with a shopping cart. In building this site you?ll also see how to build an administration panel, import and export data, and you?ll protect the site from Cross Site Scripting attacks (XSS), use form validation, and implement benchmarking.
Many PHP programmers learn PHP either as their first language (having only been exposed to XHTML and CSS beforehand) or after learning another similar language (such as Perl). Most of the time, a PHP programmer’s first few projects involve a pretty steep learning curve, but eventually the programmer finds a comfortable groove. He ends up with a project consisting of the following components:
A series of PHP pages with intermingled PHP commands, SQL queries, and XHTML
A series of JavaScript and CSS files that are linked from those PHP pages
A series of universal includesa footer file for all pages and a header file that contain the database connection and session initialization code
A handful of database tables that store the application’s data
In fact, a newbie programmer’s first PHP page probably looks a lot like this one:
<?php
include_once "db.php";
$sql = "select * from pages where status=’live’ and type=’home’ limit 1";
$result = mysql_query($sql);
while($data = mysql_fetch_object($result)){
$title = $data->title;
$css = $data->css;
$bodycopy = $data->bodycopy;
$kw = $data->keywords;
$desc = $data->description;
}
?>
<html>
<head>
<title><?php echo $title; ?></title>
<link href="<?php echo $css; ?>" rel="stylesheet" type="text/css"/>
<meta name="keywords" value="<?php echo $kw;?>"/>
<meta name="description" value="<?php echo $desc?>"/>
</head>
<body>
<?php include_once "topnav.php";?>
<div id="wrapper">
<h1><?php echo $title;?></h1>
<p><?php echo nl2br($bodycopy);?></p>
</div>
<?php include_once "footer.php";?>
</body>
</html>
So far, so good, right? The pages render quickly; there’s CSS for layout instead of tables, so it should be easy to re-skin; and life is good. The newbie programmer figures that keeping the project small enough means averting disaster. In fact, this first project does stay under a dozen PHP files in size and has one or two JavaScript and CSS files and three or four includes. Everything goes well during development, the project goes live, and the customer is happy.
Of course, the beginner programmer is usually blissfully unaware of some of the gotchas of this approach. For example, since the SQL code to retrieve the home page doesn’t have any exception handling in it, what happens if the database is unavailable (or someone accidentally erases the home page content from the DB)? The code is tied to mySQL at the moment. What if the customer changes database servers at some point?
If these thoughts occur, they’re usually put off. For now, everything works, and it’s time to celebrate and move on to the next project. “Besides,” the programmer thinks to himself, “you’re using includes for the important stuff, like database connections, global navigation, and footer content. Doesn’t that make the code more modular?”
Six months later, the programmer gets a call from the client, and the problems beginnot big problems at first, but they have a tendency to snowball. The client wants to add a few database fields, change the way the interface looks, and make the application more flexible in certain ways. Out loud, the programmer tells the client that everything is OK, but inside, a sense of low-level panic is brewing.
Why? Because the programmer barely remembers any details about the project in question six months later. Honestly, the programmer has worked on 10 other applications since that project ended, amounting to many thousands of lines of code written, rewritten, debugged, refactored, and rewritten again to meet the needs of changing requirements. This is not to mention that the programmer isn’t exactly indifferent to learning about programming, so he’s been reading books on the subject and applying what he’s learned to current projects. The programmer knows that the approach he took with this particular project is off the mark. The approach wasn’t wrong, in a strictly objective way (there are many ways to skin a cat, after all), but it sacrificed long-term support and flexibility in favor of ad hoc construction and initial speed.
Without a doubt, cleaning up the previous work will mean digging through the code to untangle PHP snippets, SQL queries, and XHTML markup; retesting everything to make sure it’s working right; and making sure that the application code and interface match the database. It’s also likely that the client will change her mind about many things along the way, requiring many course corrections (read: “rewriting code”).
Even if the request from the client is relatively simple, involving a new skin or HTML layout, the programmer could find himself carefully picking through code to make sure no vital functionality is erased. The requests get more complex from there, and all of them are filed under “Let’s hope they don’t ask for that”: supporting mobile devices, displaying content in foreign languages, rendering different views of the same data (such as pie chart versus spreadsheet), adding extensive Ajax controls, and so on.
So the programmer takes on the project, knowing full well that the relationship with the client is the most important thingthat, and a sense of pride that won’t let him hand the project over to a completely new programmer, who will probably screw it up.
The first thing he decides to take on is that crazy SQL query right on the home page. The thing to do here is to create a functions.php file in which he stores all the functions. The function for that home page content (notice the minimal exception handling) ends up looking like this:
<?php
function fetchHomePage(){
$sql = "select * from pages where status=’live’ and type=’home’ limit 1";
$result = mysql_query($sql);
while($data = mysql_fetch_object($result)){
$hp[‘title’] = $data->title;
$hp[‘css’] = $data->css;
$hp[‘bodycopy’] = $data->bodycopy;
$hp[‘kw’] = $data->keywords;
$hp[‘desc’] = $data->description;
}
if (count($hp)){
return $hp;
}else{
$hp[‘title’] = “Welcome to our web site!”;
$hp[‘css’] = “default.css”;
$hp[‘bodycopy’] = “This is our web site!”;
$hp[‘kw’] = “welcome”;
$hp[‘desc’] = “our cool site”;
return $hp;
}
}
?>
Now that the data-fetching code is in a separate file, the home page is a bit simplified. You could even say that things are a lot better now:
<?php
include_once "db.php";
include_once "functions.php";
$home = fetchHomePage();
?>
<html>
<head>
<title><?php echo $home[‘title’]; ?></title>
<link href="<?php echo $home[‘css’]; ?>" rel="stylesheet" type="text/css"/>
<meta name="keywords" value="<?php echo $home[‘kw’];?>"/>
<meta name="description" value="<?php echo $home[‘desc’]?>"/>
</head>
<body>
<?php include_once "topnav.php";?>
<div id="wrapper">
<h1><?php echo $home[‘title’];?></h1>
<p><?php echo nl2br($home[‘bodycopy’]);?></p>
</div>
<?php include_once "footer.php";?>
</body>
</html>
Soon, the programmer goes through all the PHP files and converts raw SQL into functions, depositing them into the same functions.php file. In no time at all, there exists a library of functions that extract pages, render calendar views, create RSS feeds, and do heaven knows what else. The programmer ponders this strange little file that’s become so bloated and decides to tackle it laterThere are more important things on the agenda.
So he gets to work on the rest of the client’s requests. They want to add several fields to the pages database table, and they want to check for both browser language and client type (Mozilla, Safari, IE) to push custom content out to different users. They also want to incorporate analytics tracking packages from third-party vendors. Alsoand they know it’s last minutebut one of the founders of the company just got back from a conference and is really hot on using Ajax.
Through it all, the programmer’s probably thinking, “There’s got to be a better way!” Well, there is, and it involves learning about a way of thinking called Model-View-Controller (MVC). With MVC, developers can separate their code into distinct parts, making the entire application easier to develop, maintain, and extend. Furthermore, MVC frameworks are usually pretty structured, allowing the developer to concentrate on what’s important to the client and the project at hand and not worry about other issues that affect every project (such as security and caching).
The point here is not to chastise the programmer or call out deficiencies in his approach. Everyone has been there and done that. The point is to show you a better way, inspired by a belief in the transformative power of MVC, Agile methodologies, and CodeIgniter. Believe it: All these things working together can radically change the way you work and interact with clients.
You’ll get to CodeIgniter and Agile methodologies very soon, but for now it’s time to focus on MVC concepts. Once you have a strong foundation in the basics, the rest should progress naturally. As you’ll soon see, MVC has been around for the past 30 years but has become increasingly popular of late, especially in the world of web development.
... less