Why PHP Frameworks Matter
Editor’s Note: This is a guest essay from W. Jason Gilmore, a PHP developer and bestselling author with more than ten years of professional experience. He’s the author of the popular new book, “Easy PHP Websites with the Zend Framework”, which includes access to almost five hours of online video, a periodically updated e-book, and access to a reader-restricted online forum. You can buy the book through both Amazon.com and EasyPHPWebsites.com.
In a 1998 interview with Dr. Dobb’s Magazine, creator of the Perl programming language Larry Wall concluded his answer to the final question with a tip I’ve never forgotten, remarking, “Take a good look at what you want to do, and try to come up with the long-term lazy way, not the short-term lazy way.” [1] To paraphrase another Larry Wall-ism, in the programming world “laziness is indeed a virtue”, and if you’re not a lazy programmer, then frankly you’re not trying hard enough.
Having been a PHP programmer for more than a decade, I’ve come to realize that many of my fellow PHP programmers seem to have a misplaced notion of what being “lazy” is really all about. I know that because until just a few years ago I suffered from the very same delusion. You see, PHP has a funny effect on programmers. It’s just so darned easy to use, and has so many readily available native capabilities that it’s easy to fall into the trap of believing you can rely on an amassed set of custom code libraries, tips, and tricks learned over the years in the trenches. Which is precisely what I did until about 2005, when programming suddenly got hard. In many ways 2005 was a watershed year for the Web, with among other things Jesse James Garrett setting the development world afire with the first formalized definition of Ajax [2], Google releasing the first version of its now ubiquitous mapping API, RSS really began to enter the mainstream, and a little-known company named Facebook began to receive serious venture capital infusions.
Suddenly the Web developer was facing so much more than validating user input and connecting to a database. Users began clamoring for rich interactive experiences made possible through a complex blend of JavaScript, CSS, HTML, and server-side languages. They’ve come to take for granted the ability to access Web site data through third party outlets such as RSS, and Google Gadgets. They want to use PayPal to purchase your products, and wouldn’t mind knowing whether any of their Facebook friends are also regular users of your site.
Suddenly the need to be a lazy programmer was more important than ever.
Enter the PHP Framework
With all of these new responsibilities being placed on the developer, it isn’t by accident that 2005 also happened to be the year in which all three of PHP’s major Web frameworks were born. The first public versions of CakePHP, symfony, and the Zend Framework all hit the Web, with another popular framework named CodeIgniter following soon thereafter with its first release in early 2006. With each seeking to lessen the burden on developers by abstracting away many of the programmatic tasks which always seem to rear their ugly head no matter the project type or scale.
Using a framework, developers are able to forego decisions such as where to place configuration information, how to go about validating user input, and whether to store user session information in a file or database. Also gone are the need to mix the Web site’s logic, page templates, and database-related code, because the conventions enforced by the framework go a long way towards making the separation a natural part of the development process.
Although I’ve used all of the aforementioned frameworks to varying degrees, I’m most familiar with the Zend Framework (insomuch that I wrote a book on the topic), and so thought I’d devote the remainder of this essay to several Zend Framework-related examples which illustrate just how much these solutions have to offer. Hopefully, these examples will be enough to convince those of you not already using a framework to learn more about one of these fantastic solutions.
Staging Features and Configuration Consolidation
When developing a Web site, you’ll typically be working with three versions: a development version hosted either on your laptop or on a local office server, a beta version which has been deployed to a hosting environment identical to that used for the third version, namely the production version which is made available to your audience. To compound this problem of version juggling, you’ll often use different configuration parameters for each version. For instance, if you’re using a database, then you’ll likely have different connection credentials for each site version. You’ll also want to suppress the display of errors within your production version, but make sure all errors are prominently reported on the development version.
To help you manage these versions, each Zend Framework-powered Web site uses a configuration file named application.ini, a sample of which is displayed below. You’ll see that in the section titled [production, PHP's error reporting is disabled, and the timezone is set to PDT, because the production server is hosted on the West coast. In the [development] section, error reporting is enabled, and the timezone is set to EDT because my test server is located in Columbus, Ohio. In both sections you’ll also find database-specific connection parameters.
[production] phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 phpSettings.date.timezone = "PDT" resources.db.adapter = PDO_MYSQL resources.db.params.dbname = "easyphpwebsites_prod" resources.db.params.username = "webuser_prod" resources.db.params.password = "secret" resources.db.params.hostname = "localhost" resources.db.isDefaultTableAdapter = true [development : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 phpSettings.date.timezone = "EDT" resources.db.adapter = PDO_MYSQL resources.db.params.dbname = "easyphpwebsites_dev" resources.db.params.username = "webuser_dev" resources.db.params.password = "secret" resources.db.params.hostname = "localhost" resources.db.isDefaultTableAdapter = true
To migrate between versions, all you need to do is change a single setting in an .htaccess file which determines the Web site version each server should be using.
Data Validation
Anyone who has built even a simple Web site knows how painful data validation can be. But it’s a necessary evil; if you don’t validate user input, it’s only a matter of time before your Web site data is stolen, deleted, or otherwise changed in a way that can be harmful to other users. Because of the importance of this task, the Zend Framework developers have taken great pains to create a powerful data validation feature capable of parsing even the most complex strings.
A great example of these capabilities involves validation of an e-mail address. Because of all of the possible variations, regular expression syntax used to validate an e-mail address can be extremely complex. For instance, here’s one way to do it:
if (preg_match(
'/^([_a-z0-9-+]+)(\.[_a-z0-9-+]+)*@([a-z0-9-]+)
(\.[a-z0-9-]+)*(\.[a-z]{2,6})$/', 'jason@example.com')) {
echo 'Valid e-mail address!';
}
That’s not a pretty sight. Thanks to the Zend Framework, validating an e-mail address is as simple as this:
// E-mail address
if (! Zend_Validate::is($this->_request->getPost('email'), 'EmailAddress')) {
$this->view->errors[] = "Invalid e-mail address.";
}
Database Operations
I’m not afraid to say it; I hate SQL, and a shiver runs down my spine every time I see SQL statements and PHP code mixed together. Mixing two languages together in this fashion has never seemed natural, and so the Zend Framework’s database abstraction capabilities is undoubtedly my favorite feature.
Using this feature, you communicate with the database tables using an object-oriented interface, completely removing the need to write SQL statements. Here’s a simple example which should nonetheless really demonstrate the power of this feature. Suppose you built a Web site which stored information about your favorite video games. The table schema looks like this:
CREATE TABLE games ( id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, description MEDIUMTEXT NOT NULL );
Retrieving all rows of this table within your Zend Framework-powered Web site is as simple as this:
$gameTable = new Zend_Db_Table('games');
$this->view->games = $gameTable->fetchAll();
Within the corresponding page you can loop through the $this->view->games array as you would any other:
foreach($this->games AS $game) {
echo "{$game->name}<br />";
}
The Zend Framework offers many advanced database features which allow you to account for table relations, create joins, and much more.
Display Helpers
When building the Web site’s interface, you’ll often create programmatically-driven visual representations of data which might appear within several different places on the site. Using a Zend Framework view helper, you can greatly reduce the amount of code and effort required to build these features. For instance, we can create a view helper which converts an integer value used to represent the number of stars a visitor has assigned a game when writing a review of the game into a string of star icons which considerably improve the page’s design, as shown in Figure 1.
Figure 1. Creating a starred review
This view helper is packaged into an object-oriented class, and looks something like this:
class My_View_Helper_Stars extends Zend_View_Helper_Abstract
{
/**
* Converts rating integer to star icons
*
* @param integer $rating
* @param string $stars
*/
public function Stars($rating)
{
$star = "<img src='/images/icons/star.png' />";
$stars = "";
for($i=1; $i <= $rating; $i++)
{
$stars .= $star;
}
return $stars;
}
}
With this view helper now available to your Web site, you can call the helper as necessary within your layout, as demonstrated here:
<h1>The Latest <?= $this->reviews->Title; ?> (Xbox 360) Reviews</h1>
<?php foreach($this->reviews->CustomerReviews AS $review) { ?>
<h3><?= $this->Stars($review->Rating); ?> <?= $review->Summary; ?></h3>
<p>
Posted on <?= date("F d, Y", strtotime($review->Date)); ?><br />
<?= $review->Content; ?>
</p>
<?php } ?>
Let’s break down some code:
- Line 12 defines the location of the star icon. This icon happens to be part of the spectacular FAMFAMFAM Mini icon set. Of course, for organizational reasons you might consider storing the image path in the
config.inifile. - Lines 15-18 cycle through the
forloop a number of times equivalent to the value of the$ratinginput parameter. Each time it loops, anothertag containing the
star.pngpath will be appended to the$starsvariable. - Line 19 returns the
$starsvariable to the calling view.
I think this is an ideal example of the power of view helpers because such a small amount of code adds so much to the Web site.
Third-party Plugins
I’d like to conclude this essay with some mention of the Zend Framework’s third-party capabilities. Rather than present any code, I thought I’d instead just enumerate a few of my favorite plugin features built directly into the default framework download. Click on any of the accompanying links to learn more about what these powerful features can do for you:
- Zend_Service_Amazon: Plugs into Amazon’s Product Advertising API
- Zend_Service_Flickr: Plugs into the Flickr photo sharing service
- Zend_OpenId: Plugs into Google’s Authentication, Book, Docs, Health, Apps, Search, and YouTube services
- Zend_OpenId: Plugs into the OpenID identity provision framework
Conclusion
With all of these features at your fingertips, what’s stopping you from getting lazy and building something great? I hope you enjoyed this essay, and invite you to contact me with your questions at jason@easyphpwebsites.com.
To help give you a further head start into PHP frameworks, we’ll be launching a giveaway of Jason’s latest book towards the end of this week. This post is a great sample of what you can find in the book, so be sure to check back later for your chance to scoop a copy up!
Footnotes
[1] “A Conversation with Larry Wall”, Dr. Dobb’s Magazine. February 1, 2998. http://www.ddj.com/windows/184410483
[2] “Ajax: A New Approach to Web Applications”, Adaptive Path. February 18, 2005. http://adaptivepath.com/ideas/essays/archives/000385.php


