HomePHP Page 3 - Using a Template Processor Class in PHP 5
Parsing template files: defining the input tags for the “TemplateProcessor” class - PHP
Welcome to part two of the series “Separating logic from presentation.” Comprised of three articles, this series walks you through the development of an extensible template processor in PHP 5, which you might find quite useful for separating the logic of your PHP applications from their visual presentation.
Right, I think the best way to demonstrate the functionality of my “TemplateProcessor” class is simply by feeding it a considerable variety of data, which will be eventually parsed and displayed within the corresponding template file, after performing the replacement of placeholders. Considering this, I’ll first define two dynamic files, “header.php” and “footer.php” respectively, which will compose the header and footer sections of a sample web page. Take a look at these two basic PHP files:
<?php echo '<h1>This is the header section and was generated at the following time '.date('H:i.s').'</h1>'; ?>
<?php echo '<h1>This is the footer section and was generated at the following time '.date('H:i.s').'</h1>'; ?>
Now, after listing the above PHP files, I’ll include a simple MySQL result set as part of the input of the “TemplateProcessor” class. To do this, I’ll use two additional MySQL wrapping classes, which are listed below:
// define 'MySQL' class class MySQL{ private $host; private $user; private $password; private $database; private $connId; // constructor function __construct($options=array()){ if(!is_array($options)){ throw new Exception('Connection options must be an array'); } foreach($options as $option=>$value){ if(empty($option)){ throw new Exception('Connection parameter cannot be empty'); } $this->{$option}=$value; } $this->connectDb(); } // private 'connectDb()' method private function connectDb(){ if(!$this->connId=mysql_connect($this->host,$this- >user,$this->password)){ throw new Exception('Error connecting to MySQL'); } if(!mysql_select_db($this->database,$this->connId)){ throw new Exception('Error selecting database'); } } // public 'query()' method public function query($sql){ if(!$result=mysql_query($sql)){ throw new Exception('Error running query '.$sql.' '.mysql_error()); } return new Result($this,$result); } } class Result{ private $mysql; private $result; // constructor public function __construct($mysql,$result){ $this->mysql=$mysql; $this->result=$result; } // public 'fetch()' method public function fetch(){ return mysql_fetch_array($this->result,MYSQL_ASSOC); } // public 'count()' method public function count(){ if(!$rows=mysql_num_rows($this->result)){ throw new Exception('Error counting rows'); } return $rows; } // public 'get_insertId()' method public function getInsertId(){ if(!$insId=mysql_insert_id($this->mysql->connId)){ throw new Exception('Error getting insert ID'); } return $insId; } // public 'seek()' method public function seek($row){ if(!int($row)&&$row<0){ throw new Exception('Invalid row parameter'); } if(!$row=mysql_data_seek($this->mysql->connId,$row)){ throw new Exception('Error seeking row'); } return $row; } // public 'getAffectedRows()' method public function getAffectedRows(){ if(!$rows=mysql_affected_rows($this->mysql->connId)){ throw new Exception('Error counting affected rows'); } return $rows; } // public 'getQueryResource()' method public function getQueryResource(){ return $this->result; } }
Now that you saw the source code of the two MySQL wrapping classes listed above, which I’ll utilize for fetching a trivial MySQL result set, the next thing to do is define the structure of a sample template file, named “default_template.htm,” that will be parsed in turn by the “TemplateProcessor” class. Please look at the signature of this example template file:
As you can see, the sample template file shown above has some placeholders located in different sections of the web page, which will be removed and replaced with actual data. In this example, both {header} and {footer} placeholders will be replaced with the dynamic output of the “header.php” and “footer.php” files respectively, while {maincontent} will be filled with the MySQL data set that I mentioned before. In addition, the nested {navbar{subnavigationbar1}{subnavigationbar2}} placeholders will be replaced with the contents of the following navigational PHP files:
Right, I think that all the above dynamic PHP files, in addition to the MySQL dataset that will be fetched in turn, are enough input data for feeding the input of the “TemplateProcessor” class and seeing how it works. Therefore, go ahead read the next section to see how the corresponding template file is parsed.