PHP DevCenter

oreilly.comSafari Books Online.Conferences.

We've expanded our LAMP news coverage and improved our search! Search for all things LAMP across O'Reilly!

Search
Search Tips

advertisement

Listen Print Discuss Subscribe to PHP Subscribe to Newsletters

Migrating to Page Controllers

by Ethan McCallum
10/14/2004

Mixed code/HTML tools--PHP, JSP, ASP, and so on--give web developers the power to create dynamic sites with little effort. They also make it easy to slip into bad habits. Consider the all-in-one page, or Model 1 architecture, in which a lone page handles an entire action by itself, typically in poor fashion. An example page might display a form, validate the submission, process the data, and show the user a thank-you message.

Developers can maintain their sanity by refactoring such an app or redesigning it in flight. The refactoring cure for the all-in-one page is the Page Controller. This design pattern is appropriate in places where a single component has the dual responsibilities of logic and display.

This article will explain how Page Controller works, when to use it, and how to refactor your multifunction pages. It includes a sample implementation in PHP, but in true pattern style it's quite portable. Case in point: I first stumbled across the Page Controller pattern in J2EE apps.

Theory

Most design patterns take advantage of the notion of loose coupling, in which an app's components know only enough about one another to do their job. Such modularity permits developers to change or replace components with little impact to any others. The Page Controller pattern achieves loose coupling by distilling an action into elements of logic and presentation.

Consider the flowchart in Figure 1. It describes how an app might pull data from a database and display it for the user. The three diamond shapes indicate opportunities for the process to deviate: when the app connects to the database, when it processes the query, and when it counts the number of results. Each error condition presents the user with a different error page.


Figure 1
Figure 1. A flowchart for a database application. Click on the image for a full-size screenshot.

You could certainly cram the entire flowchart into a single component. That may seem tempting at first, but the complications eventually will outweigh the convenience. Changes to this page may introduce defects in calls to business logic or HTML formatting, and testing just one piece is difficult if not impossible.

By comparison, a Page Controller implementation separates this action according to the dotted lines in the figure: the controller encapsulates the logic (the diamonds on the left), and four separate views handle the presentation (for "success" and the various errors).

The controller acts as a router for the presentation layer, choosing between the views based on the decisions in the diamonds. It can store data, such as the results of a database query, in a known location for the view to fetch and format for the user.

Such a setup is an improvement over a single, all-encompassing page, because changes to any one component affect only those components directly related to it. Components are therefore easier to reuse and to test in isolation.

Structure and Practice

From a code perspective, the controller is the PHP page (or servlet, or CGI, or whatever) called when a user accesses the Uniform Resource Identifier (URI). Implementing a Page Controller is as simple as knowing how to dispatch to a view page and store data.

Dispatching is a language-specific concern. If you're familiar with Java, you may have used RequestDispatcher#forward() to pass control from a servlet to a JSP. PHP developers have include(). That function parses the specified file, so it may include PHP code as well as plain HTML.

A file loaded by include() falls under the same scope as its caller. A variable declared in the controller is visible to the included view page. The sample code uses an array instead of a scalar variable, so view pages find their required data based on a known key in that array.

The following code excerpt is a skeleton of such a controller:

<?php

// ... perform database call
$db        = pg_connect( ... ) ;
$dbResults = pg_query( ${db} , ${dbQuery} ) ;

if( ! ${dbResults} )
{
  // store data where the error page can find it
  // ($viewData is visible in the include()'d page's scope)
  $viewData[ 'ErrorMessage' ] = "Error fetching data" ;

  // dispatch to an error page
  include( 'sql-error.php' ) ;
  return ;

}
else if( 0 == pg_num_rows( ${dbResults} ) )
{
  $viewData[ 'ErrorMessage' ] = "No results from query" ;

  // dispatch to another error page
  include( 'no-results.php' ) ;
  return ;
}
else
{
  // ... convert results into custom objects and store them
  // in $someResults ...
  $viewData[ 'results' ] = ${someResults} ;

  // dispatch to "success" page
  include( 'success.php' ) ;

  // ...
}

?>

All of this dispatching is opaque to end users and the web server software itself: they see only the request URI, which triggers the action behind the scenes.

Pages: 1, 2

Next Pagearrow




Tagged Articles

Post to del.icio.us

This article has been tagged:

php

Articles that share the tag php:

Understanding MVC in PHP (477 tags)

The PHP Scalability Myth (123 tags)

The Dynamic Duo of PEAR::DB and Smarty (53 tags)

PHP Form Handling (43 tags)

Very Dynamic Web Interfaces (39 tags)

View All

webdev

Articles that share the tag webdev:

Rolling with Ruby on Rails (351 tags)

Very Dynamic Web Interfaces (163 tags)

Understanding MVC in PHP (96 tags)

A Simpler Ajax Path (93 tags)

Ajax on Rails (61 tags)

View All

designpatterns

Articles that share the tag designpatterns:

Form Your Own Design Pattern Study Group (14 tags)

J2EE Design Patterns (7 tags)

Understanding MVC in PHP (7 tags)

Building a PHP Front Controller (4 tags)

Migrating to Page Controllers (2 tags)

View All

Sponsored Resources

  • Inside Lightroom
Advertisement

Sponsored by:

O'Reilly Media

©2009, O'Reilly Media, Inc.
(707) 827-7000 / (800) 998-9938
All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.
About O'Reilly
Academic Solutions
Authors
Contacts
Customer Service
Jobs
Newsletters
O'Reilly Labs
Press Room
Privacy Policy
RSS Feeds
Terms of Service
User Groups
Writing for O'Reilly
Content Archive
Business Technology
Computer Technology
Google
Microsoft
Mobile
Network
Operating System
Digital Photography
Programming
Software
Web
Web Design
More O'Reilly Sites
O'Reilly Radar
Ignite
Tools of Change for Publishing
Digital Media
Inside iPhone
O'Reilly FYI
makezine.com
craftzine.com
hackszine.com
perl.com
xml.com

Partner Sites
InsideRIA
java.net
O'Reilly Insights on Forbes.com