beginner: simple templating system?
#1
Posted 26 January 2012 - 04:19 PM
On the website I'm working on, there are a few common features to each page i.e. nav bar, footer, banner. But if I need to make a change e.g. add a link to the nav bar... then I have to edit the html of every single webpage..
So, in a nutshell, my question is: Is there a simple way to only make the change once and it automatically reflect throughout every other page in the website.
Thanks in advance.
Matt
#2
Posted 26 January 2012 - 06:05 PM
I'll assume you have some PHP knowledge and aren't a complete beginner, seeing as you are asking about template engines. If this goes over your head I'll gladly explain it, or you can discard it as "eek".
I'll show you a simplified example of mine, you'll have a few classes, you don't really need to know how they work as such, just use them. Though I'll explain them to some extent.
So here goes, I don't think this is too complex, its a pretty basic OO application framework for websites, really basic as I've just simplified the skeleton.
But it is Object Orientated.
So you have your root script (i.e. index.php) and then an initialization script which is included, which sets up your database and such.
Here are the scripts you'll need to create:
index.php (this is your page if you like)
global.php (this is your initialization script)
./includes/config.php (this holds your database configuration settings)
./includes/class_core.php (this holds your websites core functions)
./includes/class_mysql.php (this holds your database functions, to connect, query etc.)
./includes/class_template.php (this is the template engine)
I'll show you the code for each
Starting with index.php
<?php
// -------------------------------------------------------------------------------------------------------
// Require Application Backend
// -------------------------------------------------------------------------------------------------------
// This is your global initialization script
require_once('./global.php');
... The code for the script goes here, I'll show you how to output a template generated page in a moment ...
// End of Script
?>
Now global.php is your initialization script, you will call this in every script (i.e. index.php, about.php). You could also use a bootstrap but we don't want to overload you.
global.php:
<?php
// Set the current working directory
define('CWD', (($getcwd = getcwd()) ? $getcwd : '.'));
// -------------------------------------------------------------------------------------------------------
// Require Application Core (these are classes in the includes folder
// -------------------------------------------------------------------------------------------------------
require_once('./includes/class_core.php'); // The application core
require_once('./includes/class_database.php'); // The database class
require_once('./includes/class_template.php'); // Template Engine Class
// Initialize the application (so we can access functions in the class_core.php script, from $appCore like this:
// $appCore->function_name()
$appCore = new appCore();
// Fetch your database configuration
$appCore->fetch_config();
// Instantiate your database (so we can use functions in the class_database.php script using $db)
$db = new appDatabase();
?>
Now the config.php file, this is just a script that has some variables in it, that you set to your databases connection settings.
<?php // config.php $config['database']['type'] = 'mysql'; $config['database']['host'] = 'localhost'; $config['database']['port'] = '3306'; $config['database']['name'] = 'databasename'; $config['database']['username'] = 'username'; $config['database']['password'] = 'password'; ?>
Now, the class_core.php script, only has one thing in it, a function to fetch those configuration settings
<?php
// This is the application core class
class appCore
{
// ---------------------------------------------------------------------------------------
// Declare variables
public $config; // Holds the database config settings
public $templatecache; // Holds a cache of our templates
// ---------------------------------------------------------------------------------------
// fetch_config()
// Fetches your database configuration settings
// ---------------------------------------------------------------------------------------
public function fetch_config()
{
// create the config array
$config = array();
// Get the configuration file
include(CWD . '/includes/config.php');
// Check size of config file
if (sizeof($config) == 0)
{
echo("config.php does not exist");
exit;
}
// Put the contents of config.php into the config array
$this->config =& $config;
return 0;
}
}
?>
The class_database.php script just contains some functions for interfacing with the database:
<?
class appDatabase
{
// Some variables
private $connect; // Holds the connection result
private $select_db; // Holds the DB selection result
private $sql; // Holds the SQL string to process in a query
private $result; // Holds the result of a query
private $row; // Holds records of data from the DB
private $id; // Holds the ID from an insert
private $rowcount; // Holds the number of rows a query results
// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
// Construct the class (when we instantiate the class, this is called automatically
public function __construct()
{
// Open the DB Connection
$this->open_connection();
}
// To prevent cloning
private function __clone() {}
// -------------------------------------------------------------------
// open_connection()
// -------------------------------------------------------------------
// Opens the database connection and selects the database
public function open_connection()
{
global $appCore; // This is strictly speaking bad, but for simplicity we will do it this way
// Basically that global, allows us to interface with the appCore (its what we set in the global.pgp script)
$this->connect = mysql_connect($appCore->config['database']['host'], $appCore->config['database']['username'], $appCore->config['database']['password']) or die(mysql_error());
$this->select_db = mysql_select_db($appCore->config['database']['name']) or die("Could not select Database");
}
// -------------------------------------------------------------------
// close_connection()
// -------------------------------------------------------------------
// Closes the database connection
public function close_connection()
{
mysql_close($this->connect);
}
// -------------------------------------------------------------------
// query()
// -------------------------------------------------------------------
// Query the database
public function query($sql)
{
global $querycount, $querylist;
$this->result = mysql_query($sql) or die(mysql_error() . "<br />SQL: $sql");
return $this->result;
}
// -------------------------------------------------------------------
// escape_var()
// -------------------------------------------------------------------
// Escapes a Variable that will be used in a query
public function escape_var($var)
{
$var = mysql_real_escape_string($var);
return $var;
}
// -------------------------------------------------------------------
// row_count()
// -------------------------------------------------------------------
// Returns the number of records from a query
public function row_count($result)
{
$this->rowcount = mysql_num_rows($result);
return $this->rowcount;
}
// -------------------------------------------------------------------
// fetch_array()
// -------------------------------------------------------------------
// Returns the record array for a query
public function fetch_array($result)
{
$this->row = mysql_fetch_array($result);
return $this->row;
}
// -------------------------------------------------------------------
// fetch_object()
// -------------------------------------------------------------------
// Returns the object for a query
public function fetch_object($result)
{
$this->row = mysql_fetch_object($result);
return $this->row;
}
// -------------------------------------------------------------------
// insert_id()
// -------------------------------------------------------------------
// Returns the insert_id for the last query
public function insert_id()
{
$this->id = mysql_insert_id();
return $this->id;
}
// -------------------------------------------------------------------
// real_escape_string()
// -------------------------------------------------------------------
// Performs a real_escape_string() on the passed value
public function real_escape_string($value)
{
$value = mysql_real_escape_string($value);
return $value;
}
}
?>
Now for the complicated one, the template engine... This uses some static methods, so we don't need to instantiate it like we did the other classes.
<?php
// -------------------------------------------------------------------
// template class
// -------------------------------------------------------------------
// Template Engine Class
class appTemplate
{
private $template = ''; // Template to render @var string
private static $pre_registered = array(); // Preregistered vars @var array (mixed) (template_name = array(key=>variable))
private $registered = array(); // Registered variables @var array
private static $type = "template"; // We can use this if there are different types of template
// -------------------------------------------------------------------
// create()
// -------------------------------------------------------------------
// Creates a template object and registers any preregistered vars.
public static function create($template_name, $type="template")
{
self::$type = $type;
// Create new template object
$template = new appTemplate($template_name);
// If pre_registered
if (isset(self::$pre_registered[$template_name]))
{
$template->multi_register(self::$pre_registered[$template_name]);
unset(self::$pre_registered[$template_name]);
}
return $template;
}
// -------------------------------------------------------------------
// construct()
// -------------------------------------------------------------------
// Protected constructor
protected function __construct($template_name)
{
$this->template = $template_name;
}
// -------------------------------------------------------------------
// register()
// -------------------------------------------------------------------
// Register a variable with the template
// @param string name of variable to register
// @return mixed value to be registered. This may be a scalar or an array
public function register($name, $value)
{
$this->registered[$name] = $value;
}
// -------------------------------------------------------------------
// multi_egister()
// -------------------------------------------------------------------
// Registers an array of variable with the template
// @param string Assoc array of name => value to be registered
public function multi_register($values)
{
if (!is_array($values))
{
return;
}
foreach ($values AS $name => $value)
{
$this->register($name, $value);
}
}
// -------------------------------------------------------------------
// render()
// -------------------------------------------------------------------
// Renders the template
// @param boolean We wont use this in this example
// @return string Rendered version of the template
public function render($parseexternal=false)
{
// Define global variables (yeah this is considered bad, but they are global)
global $appCore, $db;
extract($this->registered, EXTR_SKIP);
// Fetch the template
$template_code = self::fetch_template($this->template);
if (strpos($template_code, '$final_rendered') !== false)
{
eval($template_code);
}
else
{
eval('$final_rendered = "' . $template_code . '";');
}
return stripslashes($final_rendered);
}
// -------------------------------------------------------------------
// fetch_template()
// -------------------------------------------------------------------
// Fetches template from datastore or cache
// @param string Name of template to fetch
// @return string
protected static function fetch_template($template_name)
{
global $appCore, $db;
// Does the template exist in the template cache?
if(isset($appCore->templatecache["$template_name"]))
{
// Using a template from the cache
$template = $appCore->templatecache["$template_name"];
}
else
{
// Fetching the template from the database
$result = $db->query("SELECT pagetext FROM template WHERE title='$template_name'");
// Process the template
if($db->row_count($result) > 0)
{
$template_array = $db->fetch_array($result);
}
else
{
echo("The template $template_name does not exist " . $template_name);
}
$template = addslashes($template_array['pagetext']);
// Cache the template
$appCore->templatecache["$template_name"] = $template;
}
return $template;
}
}
?>
So thats your framework.
You will need a database table called "template" which has the following fields:
template(
templateid INT 11 PRIMARY_KEY AUTO_INCREMENT
title VARCHAR 100
pagetext MEDIUMTEXT
)
So how to use it?
Well you have your templates in the database, try adding these templates:
PAGE_SHELL template
name: PAGE_SHELL
<html> <head> <title>$pagetitle</title> </head> <body> $header $content $footer </body> </html>
header template
name: header
<p>This is the header for $sitename</p>
footer template
name: footer
<p>This is the footer for $sitename</p>
Now open up that index.php script and paste the following bits of code in.
At the bottom right before the ?>
$template = appTemplate::create("PAGE_SHELL");
$template->register('pagetitle', "My homepage");
$template->register('header', $header);
$template->register('footer', $footer);
$template->register('content', $content);
print_output($template->render(true));
This will print out a template, the registers are passing whatever is to be injected where the variables are in the PAGE_SHELL template.
Now above this add the following template call to set $header and $footer (we will create two templates and inject them in)
// First the header, we are basically fetching the template and putting it into the $header variable
$template = appTemplate::create("header");
$template->register('sitename', "My Site");
$header= $template->render();
// Now we will do the footer, but slightly differently
// In the register bit, you can set these to variables, like this
$sitename = "My Web Site";
$template = appTemplate::create("footer");
$template->register('sitename', $sitename);
$footer= $template->render();
Thats a template engine. You can pre register the header and footer, so you don't need to include them in that output template call, so they are 'globalised', same with variables.
But that might be making it all a bit too complicated.
This post has been edited by FizixRichard: 26 January 2012 - 06:20 PM
#3
Posted 26 January 2012 - 07:46 PM
Go to one typical page, cut out the html or php code that repeats on every page and put it in a separate file called nav.inc (no html, head or body tags, just the code that repeats). Do the same for the footer code and call that footer.inc. Do the same for the header code and call that header.inc
Then place <?php include ("header.inc"); ?> where the header was, <?php include ("nav.inc"); ?> where the nav code was and <?php include ("footer.inc"); ?> where the footer code was.
Cut out the same code and replace with the above in all the other main pages. All the main pages will need .php extension if they have .html at present.
Then when you need to edit the footer, you only have to edit one file. Same for the others. It won't process on your local computer unless you have a server like Apache, so you may have to upload to test or install WampServer 2 which includes Apache server.
This post has been edited by Wickham: 26 January 2012 - 07:54 PM
#4
Posted 26 January 2012 - 08:38 PM
#5
Posted 26 January 2012 - 09:23 PM
Fulmar, on 26 January 2012 - 08:38 PM, said:
Your a beginner. There is no need for PHP you can use SSI to include one html file in another.
Create a file like header.html or nav.html etc and put your navbar code in there. You can then include the navbar on all pages with:
<!--#include virtual="path to file/include-file.html" -->
Your hosting needs to support SSI for this to work. Give it a try.
This post has been edited by The Web Solution Provider: 26 January 2012 - 09:24 PM
#6
Posted 26 January 2012 - 09:44 PM
The Web Solution Provider, on 26 January 2012 - 09:23 PM, said:
Create a file like header.html or nav.html etc and put your navbar code in there. You can then include the navbar on all pages with:
<!--#include virtual="path to file/include-file.html" -->
Your hosting needs to support SSI for this to work. Give it a try.
Doesn't SSI have to have a .shtml file extension? I'll have to test whether it works with a .html extension.
http://blog.dreamhos...x.cgi?area=2065
However, SSI is the poor man's PHP, hardly ever used now. I advise using PHP which will mean changing all main page extensions from .html to .php but as you may later want to add more PHP it will future-proof it.
This post has been edited by Wickham: 26 January 2012 - 09:45 PM
#7
Posted 27 January 2012 - 10:54 AM
Wickham, on 26 January 2012 - 07:46 PM, said:
Your right, the OP could do that. I just wouldn't call PHP includes 'templating' as such. I simply provided it as its what I use and its not exactly complicated.
Fulmar, on 26 January 2012 - 08:38 PM, said:
If you don't know PHP at all, Wickham's approach will be much easier, but when you know PHP I'd look at using the kind of engine I described.
The Web Solution Provider, on 26 January 2012 - 09:23 PM, said:
Create a file like header.html or nav.html etc and put your navbar code in there. You can then include the navbar on all pages with:
<!--#include virtual="path to file/include-file.html" -->
Your hosting needs to support SSI for this to work. Give it a try.
Wow, I forgot SSI existed lol. You *could* do that, but I'd still at least use PHP includes.
#8
Posted 27 January 2012 - 06:10 PM
Help

















