I first started building PHP web applications in 1997 when PHP was in version 3. Templating systems didn't exist then; object-oriented design was not a viable option; and the PHP code was downright ugly. Today, I work with PHP 5, which has a vastly improved object-oriented programming environment, mature templating systems, hundreds of useful PEAR packages, and powerful open source databases. With these advances, it's no longer acceptable to write PHP code that looks like linguini that's been thrown against the wall.
PHP now enables you to build robust, manageable, and beautiful enterprise web applications. The best way to do that is to divide the application into three components: model, view, and controller. In other words, you need to separate the presentation, the database, and the business logic from each other. The most common approach for achieving this design goal is to adhere to a strict Model-View-Controller (MVC) framework (see Sidebar 1. A Brief History of MVC).
The greatest advantage to separating the application into discreet components is that you end up with software that doesn't scare fellow developers. Instead, you create an application that developers can be update, tweak, and manipulate without requiring major rewrites and aggressive re-factoring. The MVC architecture also will greatly improve your relationship with the marketing and business development departments, because they always want to make changes and with a well-designed application you can accommodate them.
The most effective way to build a PHP application based on the MVC design pattern is to leverage the power of a templating system such as Smarty for the Viewer, a PostgreSQL database as the Model, and object-oriented PHP classes as the Controller. This article demonstrates such an MVC framework by walking through the steps for building a simple newsreader called Amalgamate.
For the demo newsreader application, the Model will consist of a PostgreSQL database, leveraging its powerful PL/pgSQL language to encapsulate all the SQL statements inside the database using stored procedures. The advantages of using stored procedures are speed, decoupling the Model from the Controller, and manageability. See Listing 1 for the complete database schema for the Amalgamate database.
According to the PostgreSQL documentation: "With PL/pgSQL you can group a block of computation and a series of queries inside the database server, thus having the power of a procedural language and the ease of use of SQL, but with considerable savings because you don't have the whole client/server communication overhead."
Also, if you put all of your SQL in stored procedures, you will cleanly separate your Model component from the Controller. See Listing 2 for the stored procedures you will use in your PHP classes to interact with the data model.
Theoretically, the separation of your Model component from the Controller could allow you to easily swap your PostgreSQL database with, say, an Oracle database. However, planning to build an application with one database and then swapping that database with another one later on rarely works; that swap is never an easy task. The best reason to move your SQL into the database is because it makes for much cleaner code. When you need to make changes to your SQL, you don't have to go into your PHP classes and make bold modifications.
So that's your Model: a PostgreSQL database with stored procedures.
The View component of your application consists of two parts: simple PHP scripts and HTML templates.
Amalgamate's HTML templates are Smarty templates. Smarty is the most mature, robust, and developer-friendly templating system available for PHP. With Smarty, you keep all of your PHP out of your HTML.
The simple PHP scripts for Amalgamate will reside in your web server document directory. These scripts are what the user hits with their browser. The basic functionality here is to instantiate any objects you may need (such as a Smarty template object), call the necessary methods to do what the user wants, and then render the HTML (i.e., View).
You call object methods here in the View, but you don't define business logic--that's what the Controller is for. The only PHP code you put in these PHP scripts relates to making the Viewer work properly. Actually, you also include the necessary files (i.e., PHP classes) and set up the database connection. You then pass a reference to that database connection to your classes when you instantiate objects. See Listing 3 for the complete Viewer code (index.php).
Author Note: In Amalgamate, the PHP scripts and the Smarty templates all exist within the web server document directory for ease of use. However, I highly recommend you store your HTML templates and Smarty's cache directory outside the web server document root.
Author Note: If you get this message: Fatal error: Smarty error: unable to write to $compile_dir, you need to adjust the permissions on the ctemplates directory under AmalgamateTemplates so that the web server can write to it.
The Controller component of Amalgamate is where your business logic goes. This is where you put the nuts and bolts of your application. And you do that by setting up several classes that know which stored procedures to call in order to fetch or manipulate the database.
Your simple Viewer PHP scripts instantiate these Controller objects and call the necessary methods. Your Smarty templates then render the appropriate member variables in the user's web browser. The Controller objects will throw exceptions when they run into errors, and the Viewer PHP will react appropriately by either dying or rendering an error page. See Listing 4 for the complete listing of all Amalgamate classes (Amalgamate.php).
Author Note: Like your Smarty templates, Amalgamate's Controller classes are stored in the web server document root. However, for security purposes, I highly recommend you store these classes outside of the web server document directory. As a general rule, make only the files that need to be accessible to the web accessible--usually Viewer PHP scripts and accompanying images.
MVC as Best Practice
The double-edged sword of PHP is that unlike Java, which forces you into an object-oriented mindset and pushes you towards writing software in a particular style, it allows you to design your application however you want to. Take it from someone who's been writing PHP code for more than 12 years, the Model-View-Controller architecture is the best way to go. In fact, any seasoned developer knows that proper decoupling, encapsulation, and abstraction are required when building quality software.
Since the release of PHP 5, the once clunky server-side procedural scripting language has become a powerful object-oriented programming environment. And if you combine the power of PHP with a nice templating system such as Smarty and a powerful database such as PostgreSQL, you can cleanly isolate the Viewer of your application from the data Model and Controller. Now you know how.
About the Author
Keith Vance is a software engineer and a journalist. He's been developing web applications professionally since 1997, and he received his journalism degree from the University of Washington in 2008. to e-mail him.