The Template Pattern

One of the major concepts behind the object orientated methodology is code reuse. When coding their application developers are encouraged to split large pieces of functionality up into smaller objects, each designed to accomplish a specific task. These objects should be generic enough to be used in other applications. Our MysqlDB and DBQuery object are two examples of objects which are likely to be used in more than one application.

The Template pattern modifies the logic of a class to make it more complete or more specific. Several examples of this have already been demonstrated earlier in this tutorial through the use of inheritance. The template pattern can also be used however to make create an instance specific class, which though the use of the constructor, initialises all the required properties.
Let us take the MySqlDB object as an example. Before any of its functions can be used, the connect() function must be called and supplied the hostname, user name and password for the server. A database also needs to be select. The connection information will often remain constant in your application, therefore an object template can be created that extends the MySqlDB object.
PHP Code:
class ProdMySqlB extends MySqlDB
{
    public function 
__construct($dbname null)
    {
        
/* connection credentials */
        
$host 'production.example.com';
        
$user 'username';
        
$password 'password';

        
$this->connect($host$user$password); // make the connection

        
if (! is_null($dbname)) {
            
$dbname $this->escape_string($dbname);

            if (! 
$this->query("use $dbname")) {
                throw new 
Exception("Error selecting database.");
            }           
        }
    }
}

class 
SatgeMySqlB extends MySqlDB
{
    protected 
$log;

    public function 
__construct($dbname null)
    {
        
$log = new Log('dbquery.log'); // create a Log file object

        /* connection credentials */
        
$host 'staging.example.com';
        
$user 'username';
        
$password 'password';

        
$this->connect($host$user$password);

        if (! 
is_null($dbname)) {
            
$dbname self::escape_string($dbname);

            if (! 
$this->query("use $dbname")) {
                throw new 
Exception("Error selecting database.");
            }           
        }
    }

    public function 
query($query)
    {
        
$this->log->write_log("Executing query: $query"); // add query text to the log

        
return parent::query($query);
    }

The above example creates two new subclasses of MySqDB. One for a production server (i.e: the live site) and one for a staging server, which is used to test the code before it is moved to the production server. The connection information is now contained within the class constructor which takes an optional single argument that preselects the database. You can now create a connection specific instance of either class as follows:

PHP Code:
$db = new ProdMySqlDB('exmaple'); // creates production connection and preselects the example database 
What are the advantages of this and why use it?
You can use the template pattern in this fashion has several advantages:
  • Creating instance specific classes for any object in your application means that should the initialisation information (i.e: the connection information in the above example) were to change. It need only be changed in one place.
  • As it is an implementation of inheritance, the template pattern enables you to extend the functionality of the object and add extra features. The SatgeMySqlB, creates an instance of a Log file object (not defined here) and writes each query executed to the log. Useful on a staging server where the need to debug code and database queries often arises.
  • Lastly, through the use of the template pattern you can create several versions of the same object with different instance specific initialisation data, as demonstrated above. A factory function can then be defined which selects the most appropriate object based on the current environment:
    PHP Code:
    function create_db()
    {
        
    $ip $_SERVER['SERVER_ADDR']; // get the servers IP address

        
    switch($ip) {
            case 
    '10.10.1.5'// staging server
                
    return new StageMySqlDB('example');
            default: 
    // all other IP's signify this is the live site
                
    return new ProdMySqlDB('example');
        }



Creating an instance of the MySqlDB object and connecting to the database is now as simplae as:
PHP Code:
$db create_db(); // executes the factory function 
Conclusion

In this series of articles I have taken you through new features provided by the PHP 5 object model and demonstrated how design patterns (methods of solving common OOP related problems) can be applied through PHP. You should now be equipped with the knowledge needed to effectively use PHP 5's new object model. In using it effectively, you will produce more efficient, scalable and robust applications, while making the job of coding it easier.


If you have any comments regarding this tutorial please post them here, not in this thread.