Introduction
This tutorial extends on the previous tutorial of the Fully Functional Simple Template Engine. There would be some functions edited and I would finally provide you with the caching capabilities here.
Before I start on this, let me confess... the caching class I'm about to unleash is not written by me... I found it somewhere here on OZZU and assumed it was ok for me to use... since it works just like I need it to, I didn't find any need to recode myself another one, even though I could (I promise... I really can 🤣 )
This tutorial is not, by any means, the last tutorial based on this Fully Functional Simple Template Engine... when I make enough edits to the class to fill up a big page with edits and if it teaches you with something... then I'll post another one here... but it could be the last 🤣
Added
Let's start by adding some more functions here: The function is called include_file.
<?php
function include_file($file)
{
}
?>
The reason for it being is that sometimes you want to put in a filename to be set to a variable, but you don't want to actually include the contents of it into the template... so I made a simple solution here... for every file that you DON'T want to include into the file, just add a '' in front of it... the '' is perfect because it isn't allowed in the filename to be set when you create a file and it lets us create this functionality 🙂
<?php
function include_file($file)
{
// Taking the first character from the filename
$find = substr($file, 0, 1);
// Checking if * exists in $filename
if($find != '*')
{
return true;
}
return false;
}
?>
What this function does is check the very first character of the filename provided for '*'. If you don't like this method, you can substitute the function with the following.
<?php
function include_file($file)
{
// Checking if * exists in $filename
if(strpos($file, '*') != false)
{
return true;
}
return false;
}
?>
That way is using a smaller amount of code, but this time, you can put the asterisk '*' anywhere in the filename... it's not limited to being at the front.
The next function is what I named to be unclude_file. It generally does what the above function does, but it also removes the asterisk for sanitation.
<?php
function unclude_file($file, $perform = false)
{
// Checking if the file was passed as an un-includeable
if($this->include_file($file) === false)
{
// Checking if we should actually remove the first character (It being the '*')
if($perform == true)
{
// Counting the number of letters $file consists of
$ltrs = strlen($file);
// Returning the trimmed $file
return substr($file, 1, $ltrs);
}
return true;
}
return false;
}
?>
I guess you could put all of this into one function if I really think about it, but I'll break it up into to... why? Because I'm too lazy to edit this tutorial to accommodate the change 🙄 🤣
Also, I add a variable to the whole class called include_files. It holds true if you want the files that are passed into the variable def. to be included into the template (As in their contents) or not included into the templates (Only the file names would be included... not the source).
<?php
class tpl {
// Various variables used throughout the class
public $vari, $template, $page, $vstart, $vend, $include_files;
}
?>
The variables in blue is what I just put into there to make it more correct (?). I set them in the function start and use them in a few functions... in the class
Edited
Right, I said I edited some functions, so let's get on it 🙂
The first function I edited was the svariable to accommodate the include_file() function and the unclude_file() function. Here it is in it's full glory 😁
<?php
function svariable($return = false)
{
// Converting set variables to the text defined in the parent PHP file
foreach($this->vari as $key => $value)
{
// Checking if the value is a file and if it exists if it is a file
if(is_file($value) && file_exists($value))
{
if($this->include_files === true && ($this->include_file($value) === true))
{
// Getting the contents of the file
$value = file_get_contents($value);
// Replacing the KEY variable with the contents of the file
$this->text = str_replace($this->vstart . $key . $this->vend, $value, $this->text);
}
else
{
// Replacing the KEY variable with the value
$this->text = str_replace($this->vstart . $key . $this->vend, $value,$this->text);
}
}
else
{
if($this->unclude_file($value) === true)
{
$value = $this->unclude_file($value, true);
}
// Replacing the KEY variable with the value
$this->text = str_replace($this->vstart . $key . $this->vend, $value,$this->text);
}
}
// Checking if we need to return the result
if($return)
{
return $this->text;
}
}
?>
That is it for this one 🙂
The cache
Alright, since I took this class from someone on this forum, I'll just post the whole entire class here (Without coloring it red... I have to color every line separately... ).
What it does though, is creates a file with the variables NOT replaced... it includes all the files first and then caches it. The id (or the name it would be saved on) is the file name... so if you are using a template more then once on different PHP files... don't cache it 😁 Otherwise it will mess you up.
<?php
class fcache {
var $name = NULL; // private members only >= PHP 5
var $value = array();
var $ttl;
function __construct($name, $ttl = 3600) { // Default $ttl is 3600 (60 minutes until expiry)
$this->name = $name;
$this->ttl = $ttl;
}
function check() {
$cached = false;
$file_name = './cache/' . $this->name . ".cache";
if(file_exists($file_name))
{
$modified = filemtime($file_name);
if(time() - $this->ttl < $modified)
{
$fp = fopen($file_name, "rt");
if($fp)
{
$temp_value = fread($fp, filesize($file_name));
fclose($fp);
$this->value = unserialize($temp_value);
$cached = true;
}
}
else
{
$this->del_value($this->name);
$this->set_value($this->name, $this->value);
$this->save();
}
}
return $cached;
}
function save() {
$file_name = './cache/' . $this->name . ".cache";
$fp = fopen($file_name, "wt");
if($fp)
{
fwrite($fp, serialize($this->value));
fclose($fp);
}
}
function set_value($key, $value) {
$this->value[$key] = $value;
}
function get_value($key) {
if(isset($this->value[$key]))
{
return $this->value[$key];
}
else
{
return null;
}
}
function del_value($key)
{
$file_name = './cache/' . $this->name . ".cache";
if(file_exists($file_name))
{
unset($this->value[$key]);
return unlink($file_name);
}
return false;
}
}
?>
Now we have to put that into our gentemp.
<?php
function gentemp($cache = false, $return = false)
{
// Converting simple function variables to function
$this->sfvariable();
// Checking if the page needs to be cached... if so, cache it.
if($cache)
{
// Setting the cache class object
$cache = new fcache($this->page);
// Checking if the cache is available for the current page
if($cache->check())
{
// Retrieving the cached contents of the page
$this->text = $cache->get_value($this->page);
}
else
{
// Setting the cache with the contents of the current page
$cache->set_value($cache->name, $this->text);
// Saving the cache
$cache->save();
// Retrieving the cached contents of the page
$this->text = $cache->get_value($this->page);
}
}
// Converting simple variables to variables
$this->svariable();
// Checking if we need to echo or return the page
if($return)
{
// Returning the page
return $this->text;
}
else
{
// Echoing the page
echo $this->text;
}
}
?>
Example usage
Now, an example use of this whole thing would be:
process.php
<?php
require('includes/globals.php');
$db->connect();
$db->last_sql = $db->build_query(array('*', 'forum_a'));
$result = $db->last_sql_data(false, 'SQL Results Data', true);
$db->close();
$tpl->template = 'default';
$tpl->page = 'index';
$tpl->start();
include('includes/global_vars.php');
$tpl->vari = array_merge($tpl->vari, array(
'SQL_QUERY' => $result,
'MEMBER_STUFF' => ((isset($_SESSION['uid'])) ? 'members.html' : 'non_members.html'),
'USERNAME' => $username,
'LAST_VISIT' => date(MM/DD/YYYY hh:mm:ss, $last_visit)
'NOW_DATE' => date(MM/DD/YYYY hh:mm:ss)
));
$tpl->gentemp(true);
?>
That true in the gentemp( in the piece of code above tells the code to cache it as well.
And the template file could look like
<!-- INCLUDE header.html -->
<div id="content">
<h6 id="header">Welcome {USERNAME} your last visit was {LAST_VISIT} from today ({NOW)DATE})</h6>
<p>{MEMBER_STUFF}</p>
<p>{SQL_QUERY}</p>
</div>
<!-- INCLUDE footer.html -->
Hope that made sense 😁
Conclusion
Well, this is it for now. Hope you enjoyed it and would find a good use for it 😁
cache.php
<?php
class fcache {
var $name = NULL; // private members only >= PHP 5
var $value = array();
var $ttl;
function __construct($name, $ttl = 3600) { // Default $ttl is 3600 (60 minutes until expiry)
$this->name = $name;
$this->ttl = $ttl;
}
function check() {
$cached = false;
$file_name = './cache/' . $this->name . ".cache";
if(file_exists($file_name))
{
$modified = filemtime($file_name);
if(time() - $this->ttl < $modified)
{
$fp = fopen($file_name, "rt");
if($fp)
{
$temp_value = fread($fp, filesize($file_name));
fclose($fp);
$this->value = unserialize($temp_value);
$cached = true;
}
}
else
{
$this->del_value($this->name);
$this->set_value($this->name, $this->value);
$this->save();
}
}
return $cached;
}
function save() {
$file_name = './cache/' . $this->name . ".cache";
$fp = fopen($file_name, "wt");
if($fp)
{
fwrite($fp, serialize($this->value));
fclose($fp);
}
}
function set_value($key, $value) {
$this->value[$key] = $value;
}
function get_value($key) {
if(isset($this->value[$key]))
{
return $this->value[$key];
}
else
{
return null;
}
}
function del_value($key)
{
$file_name = './cache/' . $this->name . ".cache";
if(file_exists($file_name))
{
unset($this->value[$key]);
return unlink($file_name);
}
return false;
}
}
?>
templates.php
<?php
/* (class) templates.php
* Class defining the templating engine used throughout the site.
*
*/
class tpl {
// Various variables used throughout the class
public $vari, $template, $page, $vstart, $vend, $include_files;
// The directory where the template is located
var $dir = 'templates';
// The extension of the template files
var $ext = 'html';
/*
* FUNCTION start( void )
* Starts template processing... must be called AFTER $tamplate and $page has being defined.
*/
function start()
{
// Storing the contents of the template file into the $this->text variable
$this->text = @file_get_contents($this->dir . '/' . $this->template . '/' . $this->page . '.' . $this->ext);
// Defining certain configurable variables used in the template class
$this->vstart = '{'; // Variable replacement start delimiter
$this->vend = '}'; // Variable replacement end delimiter
$this->include_files = true;
}
/*
* function set_var($key, $value)
* @string $key - The name of the variable that would be replaced in the template file
* @string $value - The value that would replace the key ($key)
*
* To be used when setting one variable
*/
function set_var($key, $value)
{
$this->vari[$key] = $value;
}
/*
* FUNCTION svariable ( void )
* Converts simple variables to defined text... defined in $vari
*/
function svariable($return = false)
{
// Converting set variables to the text defined in the parent PHP file
foreach($this->vari as $key => $value)
{
// Checking if the value is a file and if it exists if it is a file
if(is_file($value) && file_exists($value))
{
if($this->include_files === true && ($this->include_file($value) === true))
{
// Getting the contents of the file
$value = file_get_contents($value);
// Replacing the KEY variable with the contents of the file
$this->text = str_replace($this->vstart . $key . $this->vend, $value, $this->text);
}
else
{
// Replacing the KEY variable with the value
$this->text = str_replace($this->vstart . $key . $this->vend, $value,$this->text);
}
}
else
{
if($this->unclude_file($value) === true)
{
$value = $this->unclude_file($value, true);
}
// Replacing the KEY variable with the value
$this->text = str_replace($this->vstart . $key . $this->vend, $value,$this->text);
}
}
// Checking if we need to return the result
if($return)
{
return $this->text;
}
}
/*
* FUNCTION sfvariable ( void )
* Converts simple function variables to functions... defined in the HTML template file
*/
function sfvariable($return = false)
{
// Converting simple functions variables to their PHP equivalents
$this->text = preg_replace("/\<\!-- INCLUDE (.+?) --\>/e", "@file_get_contents('templates/{$this->template}/\1')", $this->text);
// Checking if we need to return the result
if($return)
{
return $this->text;
}
}
/*
* FUNCTION include_file( string $file)
* @string $file - The filename you want to check if it needs to be included.
*
* Checks if a file needs to be included. If it doens't need inclusion, than it would
* have * in front.
*/
function include_file($file)
{
// Taking the first character from the filename
$find = substr($file, 0, 1);
// Checking if * exists in $filename
if($find != '*')
{
return true;
}
return false;
}
/*
* FUNCTION unclude_file( string $file [, bool $perform])
* @string $file - The filename to remove the first * from.
* @boolean $perform - If we should actually remove the * from
* the $file or if we should just check if the * exists in
* there.
*
* A function that checks for the * in a filename and removes the first one.
*/
function unclude_file($file, $perform = false)
{
// Checking if the file was passed as an un-includeable
if($this->include_file($file) === false)
{
// Checking if we should actually remove the first character (It being the '*')
if($perform == true)
{
// Counting the number of letters $file consists of
$ltrs = strlen($file);
// Returning the trimmed $file
return substr($file, 1, $ltrs);
}
return true;
}
return false;
}
/*
* FUNCTION gentemp ( [ bool $cached [, bool $return]] )
* @boolean $cached (Default: false) if set to true, would cache the template file before parsing the file.
* @boolean $return (Default: false) if set to true, the output would be returned rather then echoed.
* Completes the generation of the template into HTML and spits it out
*/
function gentemp($cache = false, $return = false)
{
// Converting simple function variables to function
$this->sfvariable();
// Checking if the page needs to be cached... if so, cache it.
if($cache)
{
// Setting the cache class object
$cache = new fcache($this->page);
// Checking if the cache is available for the current page
if($cache->check())
{
// Retrieving the cached contents of the page
$this->text = $cache->get_value($this->page);
}
else
{
// Setting the cache with the contents of the current page
$cache->set_value($cache->name, $this->text);
// Saving the cache
$cache->save();
// Retrieving the cached contents of the page
$this->text = $cache->get_value($this->page);
}
}
// Converting simple variables to variables
$this->svariable();
// Checking if we need to echo or return the page
if($return)
{
// Returning the page
return $this->text;
}
else
{
// Echoing the page
echo $this->text;
}
}
/*
* function list_styles( void )
*
* Function that lists all of the available styles in the templates directory
*/
function list_styles($array = false)
{
// Checking if the result should be an array or a SELECT form element
if(!$array)
{
// Starting the SELECT form element
$result = "<select name=\"style\">\n";
// Iterating through the ./templates directory looking for directories in there
foreach(new DirectoryIterator('./templates/') as $file)
{
// Making sure that we got a directory that is not the current page (would never be the case but, better be safe)
if ((!$file->isDot()) && ($file->getFilename() != basename($_SERVER['PHP_SELF'])))
{
// Making sure that the current file the pointer is on is actually a directory
if($file->isDir())
{
// Setting the options tag to the form element
$result .= "<option value=\"{$file->getFilename()}\">{$file->getFilename()}</option>\n";
}
}
}
// Finishing the SELECT form element
$result .= "</select>\n";
}
else
{
// Iterating through the ./templates directory looking for directories in there
foreach(new DirectoryIterator('./templates/') as $file)
{
// Making sure that we got a directory that is not the current page (would never be the case but, better be safe)
if ((!$file->isDot()) && ($file->getFilename() != basename($_SERVER['PHP_SELF'])))
{
// Making sure that the current file the pointer is on is actually a directory
if($file->isDir())
{
// Creating the array
$result[] = $file->getFilename();
}
}
}
}
// Returning the result
return $result;
}
}
?>
This page was published on It was last revised on