Page 1 of 1

Creating a simple dynamic website with PHP Rate Topic: -----

#1 RudiVisser  Icon User is offline

  • .. does not guess solutions
  • member icon

Reputation: 1004
  • View blog
  • Posts: 3,562
  • Joined: 05-June 09

Posted 08 August 2011 - 11:43 PM

*
POPULAR

Quote

This tutorial expects you to have a PHP web server setup and ready for testing. Preferably this would be a local server, so that as soon as you save/create a file you can visit it. Not much PHP knowledge is required, but as usual every little helps.


If you have your own static website, you may be getting sick of updating every single page when something in your header changes, a logo, a menu item, or even a single character - just to name a few examples.

This simple tutorial is going to help you step away from the perils of having to do this for every minor change, and leaving you just having to update a single file to affect many different (if not every!) page on your website.

Now let me say that there are a lot of tutorials like this on the internet already, but some of them will only take you to a very basic point and then stop. This one won't, I'm going to, after showing you the very basics, how to make your system much more advanced and dynamic like a real website is. There's no point only learning a bit, if you're essentially just going to have another static website.

So to expand, this is what we will be learning, in order of "difficulty":
  • How to create a dynamic website with header/footer
  • How to make your links prettier + friendlier (With Apache/IIS7)
  • How to make your menu dynamic (Coming soon!)
  • How to secure your system further (Coming soon!)
  • How to make your title dynamic (Coming soon!)
  • If you need more control, how to make your system into a minimal implementation of a 'VC' (MVC without the M) architecture (Coming soon!)


That's quite a lot if you ask me, so now to get started..

How to create a dynamic website with header/footer

Starting out with the very basic stuff, what we're going to accomplish here is splitting our website pages up from 1 file (for now let's use/call it index.htm) into 3 files. This file is going to become header.htm, index.htm (of course with amended contents) and footer.htm.

The first thing you need to do is identify, from the contents of index.htm, which part of your page is the header, which part is the content, and which part is the footer. This shouldn't be too bad as most sites generally have code like this (simplified):
<html>
 <head>
     <title>My cool website</title>
 </head>
 <body>
     <div id="header">
         <img src="logo.png" alt="Cool Website Logo" />
     </div>
     <div id="content">
         <p>Awesome content goes here</p>
     </div>
     <div id="footer">
         <p>Copyright 2011 Cool Site.</p>
     </div>
 </body>
 </html>



If it is, congratulations your site is written in a beautiful way and it should be fairly obvious how to split it up, your header file (header.htm) should contain everything from the top down to (and including) <div id="content">. In the same light, everything underneath (not including) <p>Awesome content goes here</p> should go into footer.htm. Finally, the single line <p>Awesome content goes here</p> will hang around in index.htm.

Now the final thing you need to do once you have those pages is move them into a folder you're going to create called templates.

Once they're in templates, you're done with the splitting, and should simply repeat the process for the rest of your pages. Remember, all you need in the files is the content, you don't need to put the header/footer in there any more, so all you'll need to do is delete contents from the other files.

The Dynamic (PHP) Bit
What we're trying to accomplish here is very simple, we're basically going to include the 3 files in order, first the header, then the content, then the footer. It's simple, and can be achieved with code such as the following:
<?php 
include("templates/header.htm"); 
include("templates/index.htm"); 
include("templates/footer.htm");

It's the simplest thing on earth, and even without any PHP knowledge you would be able to figure out exactly what it's doing. So okay, let's go ahead and place that code in a file called index.php, in the web root.

Now, when you go to your website's address, you should see your homepage exactly as it was before we made these changes. If you do, that's great, and we're making good progress!

Now comes the good stuff, we of course need to make that dynamic now, so we're going to first discuss how we're going to do that.. Firstly, the parameter that makes our site show a different page is going to be called action, this is a GET parameter, which means that it's going to be passed through the URL. So when you visit your site, instead of going to, for example, http://site/about.htm, you will now to go to http://site/?action=about. Don't worry if that looks "worse", I've included a section to clean these up later on, you can even make them the exact same if you wanted to.

So, first of all we need to grab the GET parameter into our code, so, underneath our line that includes the header template, add the following:
$action = $_GET['action'];

We now have the variable $action available for use to load our template page. But there's a problem, this is untrusted data from the user, if we were to simply go along now and do something such as include("templates/" . $action), we would be in big trouble. See, the user could visit a URL like this: http://site/?action=..../../etc/passwd, and download your password file (on a *nix system).

What we first need to do is sanitise this data. PHP has a function called basename, which we're going to use to ensure any malicious user can't change directory no matter how hard he tried. So, underneath where you're defining $action, add the following:
$action = basename($action); 


Basically, what basename is going to do is take, well, the base name of the path. This essentially translates to the filename, without any leading directory, which is exactly what we want!

So, now that we have a sanitised action name to include, let's go ahead and do it. Change index in your code (from templates/index.htm) to be $action, and we're done! Your code should now look a little something like this:
<?php 
include("templates/header.htm"); 

$action = $_GET['action']; 
$action = basename($action); 
include("templates/$action.htm"); 

include("templates/footer.htm");


So let's try it out, visit http://site/?action=index, and you should see your homepage again. Now try going to http://site/?action=about (provided you have an about.htm in templates/, otherwise something else), you should see your about page!

If you do, that's perfect, if not, you've done something wrong along the way, so read back over it and see if you can figure it out.

What if there's no ?action=

People visiting your website are not going to know that they need to use ?action=index to view your homepage, so we need to cater for people who visit without a GET parameter. This will be our default case, and by default we will be showing your home page, index.htm.

So, back to your code, you will notice that we don't check if $_GET['action'] exists before we use it, so let's do that using PHP's empty function, which will check if a variable doesn't exist, or if it's empty.

Change your code to this:
<?php  
include("templates/header.htm");  

if (!empty($_GET['action'])) { 
    $action = $_GET['action'];  
    $action = basename($action);  
    include("templates/$action.htm");  
} 

include("templates/footer.htm"); 


empty() will return true if $_GET['action'] is empty or non-existant, so our dynamic code will only be ran if it does exist, as we're using ! to flip false to true, and vice versa. The code within if ([expression]) is only ran if [expression] evaluates to true, which, based on that code above, will happen when ?action is passed across.

So now that we're only running our code when there is a parameter present, we need to write some code that's going to be ran when it's not present. We will do this in the else block of the if statement, like so:
<?php
include("templates/header.htm");   

if (!empty($_GET['action'])) {  
    $action = $_GET['action'];   
    $action = basename($action);   
    include("templates/$action.htm");   
} else { 
    include("templates/index.htm"); 
} 

include("templates/footer.htm");


So now what's happening is that, when there is no ?action sent over in the URL, we will include templates/index.htm, simple! When they do pass over ?action=something, then it will run out first set of code, just as we'd expect. Try that out now by first visiting http://site/, and then http://site/?action=about!

Once again, if everything's working, let's continue on...

http://site/?action=furballs

Now then, assuming your website doesn't have a page named furballs, visiting this URL is going to cause a nasty surprise to the user as it will throw an error saying files cannot be found.

This is because, according to your code, anything that's passed over should be loaded, so visiting this URL will attempt to load templates/furballs.htm!

We obviously don't want that, so we need to check if the file exists first, we can do this using the aptly named <a href="http://php.net/file_exists">file_exists</a> function provided by PHP. All we need to do is pass it a filename, and it will return a boolean value based on whether it exists or not!

So we're now going to amend our code to trick it into using the default if the file doesn't exists. Add an if statement as below, that will amend $action to have the value index when the file doesn't exist:
<?php 
include("templates/header.htm"); 

if (!empty($_GET['action'])) { 
    $action = $_GET['action']; 
    $action = basename($action); 
    if (!file_exists("templates/$action.htm") 
        $action = "index"; 
    include("templates/$action.htm"); 
} else { 
    include("templates/index.htm"); 
} 

include("templates/footer.htm");


Yippee! Try visiting http://site/?action=furballs, and you should get to your homepage, if you do, move on!

http://site/?action=header and http://site/?action=footer[

Argh! What happens if we go to these URLs, we'll either get the header or footer on our page twice, that's not good, so we're going add another if () statement to our code that will once again redirect users to the default page if they visit the above.
<?php
include("templates/header.htm");  

if (!empty($_GET['action'])) {  
    $action = $_GET['action'];  
    $action = basename($action);  
    if (!file_exists("templates/$action.htm"))  
        $action = "index";  
    if ($action == 'header' || $action == 'footer') 
        $action = "index"; 
    include("templates/$action.htm");  
} else {  
    include("templates/index.htm");  
}  

include("templates/footer.htm");


Once again, try out your new code! Simply visit http://site/?action=footer and http://site/?action=header, and you should get the same as when you visit http://site/ on it's own!

Tidying it all up
That's it, we've done everything that we need to, but the code just got longer and longer, so we're going to look at how to tidy it up now. Basically what we'll do is add a default value for $action, and always use the dynamic code. The only time that $action is set is when the $_GET parameter meets certain conditions.

Rather than explain it here, I'll just update the code to contain the changes, and comment it to so that you can see what's going on clearly...
<?php   
include("templates/header.htm");   

// Set the default name 
$action = 'index'; 
// Specify some disallowed paths 
$disallowed_paths = array('header', 'footer'); 
if (!empty($_GET['action'])) { 
    $tmp_action = basename($_GET['action']); 
    // If it's not a disallowed path, and if the file exists, update $action 
    if (!in_array($tmp_action, $disallowed_paths) && file_exists("templates/{$tmp_action}.htm")) 
        $action = $tmp_action; 
} 
// Include $action 
include("templates/$action.htm"); 

include("templates/footer.htm");


Now then, this is possibly going to look a bit scarier, but it's commented, and it's basically just grouped 2 things into 1 if statement. Rather than having individual if conditions for the disallowed paths, we've moved it into an array so it's easier to manage, we've also moved the default page into a variable so that we can change it at any point.

Overall, despite being a bit longer, it's more manageable!

How to make your links prettier + friendlier (With Apache/IIS7)

You've probably heard of a .htaccess or web.config file before now, and that's exactly what we're going to use. If you're using Apache as your web server, you'll need to make sure that mod_rewrite is installed. Likewise, if you're using IIS, you need to ensure that URL Rewrite 2 is installed.
Apache
RewriteEngine On
 # Simple passthru for existing files (so we can still get to files that exist!) RewriteCond %{REQUEST_FILENAME} -s [OR] RewriteCond %{REQUEST_FILENAME} -l [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.*$ - [NC,L] # Rewrite anything to index.php?action=anything (http://site/test -> http://site/index.php?action=test) RewriteRule ^(.*)$ index.php?page=$1


IIS
<?xml version="1.0" encoding="UTF-8"?> 
<confguration> 
    <system.webServer> 
        <rewrite> 
            <rules> 
                <rule name="CodeHook Website Rewrite" enabled="true" stopProcessing="true"> 
                    <match url="^(.*)$" ignoreCase="true" /> 
                                <conditions logicalGrouping="MatchAll" trackAllCaptures="false"> 
                                    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> 
                                    <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> 
                                </conditions> 
                                <action type="Rewrite" url="index_.php/{R:1}" appendQueryString="false" logRewrittenUrl="true" /> 
                        </rule> 
            </rules> 
        </rewrite> 
    </system.webServer> 
</configuration>


The rest..
The rest will be coming soon, as I need to rework my site to be able to show long tutorials in a nice manner :)

Source
This tutorial was originally written for my own website and can be found here.

This post has been edited by RudiVisser: 06 September 2011 - 05:09 AM


Is This A Good Question/Topic? 8
  • +

Replies To: Creating a simple dynamic website with PHP

#2 skorned  Icon User is offline

  • New D.I.C Head

Reputation: 13
  • View blog
  • Posts: 41
  • Joined: 30-August 08

Posted 04 September 2011 - 02:24 PM

Nice tutorial, and like you noted, the first one to really go in-depth and deal with all scenarios and potential pitfalls. Just one little typo I think I found...
Shouldn't it read (note the exclamation point):
if (!file_exists("templates/$action.htm")
        $action = "index";
   include("templates/$action.htm");


? As in, shouldn't the action be set to index only if the file does not exist?

This post has been edited by skorned: 04 September 2011 - 02:25 PM

Was This Post Helpful? 1
  • +
  • -

#3 RudiVisser  Icon User is offline

  • .. does not guess solutions
  • member icon

Reputation: 1004
  • View blog
  • Posts: 3,562
  • Joined: 05-June 09

Posted 06 September 2011 - 05:10 AM

View Postskorned, on 04 September 2011 - 10:24 PM, said:

Nice tutorial, and like you noted, the first one to really go in-depth and deal with all scenarios and potential pitfalls. Just one little typo I think I found...
Shouldn't it read (note the exclamation point): ..? As in, shouldn't the action be set to index only if the file does not exist?

Great - Updated it, thanks for that!

I had a test page going whilst typing this up, but updated each snippet rather than copy/paste so it must've got out of sync :nottalkingtoyou:

Thanks!
Was This Post Helpful? 0
  • +
  • -

#4 lokilust  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 10-April 13

Posted 10 April 2013 - 08:40 PM

How do you add a error page if $action.htm page does not exist ?
Was This Post Helpful? 0
  • +
  • -

#5 mnkhalid  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 01-July 13

Posted 01 July 2013 - 02:32 AM

View PostRudiVisser, on 06 September 2011 - 05:10 AM, said:

View Postskorned, on 04 September 2011 - 10:24 PM, said:

Nice tutorial, and like you noted, the first one to really go in-depth and deal with all scenarios and potential pitfalls. Just one little typo I think I found...
Shouldn't it read (note the exclamation point): ..? As in, shouldn't the action be set to index only if the file does not exist?

Great - Updated it, thanks for that!

I had a test page going whilst typing this up, but updated each snippet rather than copy/paste so it must've got out of sync :nottalkingtoyou:/>

Thanks!


How Do i dynamically update the title of my page ?
Was This Post Helpful? 0
  • +
  • -

#6 snug  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 06-July 13

Posted 06 July 2013 - 08:04 AM

View Postmnkhalid, on 01 July 2013 - 02:32 AM, said:

View PostRudiVisser, on 06 September 2011 - 05:10 AM, said:

View Postskorned, on 04 September 2011 - 10:24 PM, said:

Nice tutorial, and like you noted, the first one to really go in-depth and deal with all scenarios and potential pitfalls. Just one little typo I think I found...
Shouldn't it read (note the exclamation point): ..? As in, shouldn't the action be set to index only if the file does not exist?

Great - Updated it, thanks for that!

I had a test page going whilst typing this up, but updated each snippet rather than copy/paste so it must've got out of sync :nottalkingtoyou:/>/>

Thanks!


How Do i dynamically update the title of my page ?



I was just trying to do the same thing, here is what I came up with.

<!DOCTYPE html>
  <?php
    //set default name
    $action = 'index';
    //specify disallow paths
    $disallow_paths = array('header', 'footer');
    if (!empty($_GET['action'])){
      $tmp_action = basename($_GET['action']);
    //if it's not a diallowed path, and if the file exists, make $action
      if (!in_array($tmp_action, $disallow_paths) && file_exists("templates/{$tmp_action}.htm"))
        $action = $tmp_action;
    }
    echo "<html>
      <head>
        <link type='text/css' rel='stylesheet' href='stylesheet.css' />
        <title>Title - " . $action . "</title>
      </head>
      <body>";
        include("templates/header.htm");
        include("templates/$action.htm");
        include("templates/footer.htm");
      echo "</body>
        </html>";



Not sure if this is the best way to do it, but it's working for me so far. Basically if I went to domain.com/?action=test, my title would be:

Title - test
Was This Post Helpful? 0
  • +
  • -

#7 zhencode  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 26-February 14

Posted 26 February 2014 - 10:40 AM

[Not sure if this is the best way to do it, but it's working for me so far. Basically if I went to domain.com/?action=test, my title would be:]

Great job! I would improve it this way below: You can get the title using $_GET in the header.htm
<?php
  include("templates/header.php");
    //set default name
    $action = 'index';
    //specify disallow paths
    $disallow_paths = array('header', 'footer');
    if (!empty($_GET['action'])) {
      $tmp_action = basename($_GET['action']);
    //if it's not a diallowed path, and if the file exists, make $action
      if (!in_array($tmp_action, $disallow_paths) && file_exists("templates/{$tmp_action}.php")) {
        $action = $tmp_action;
       } else {
          $action = 'notfound';
       }
          include("templates/$action.php"); //allowed page
    }
   	include("templates/$action.php"); //disallowed/unavailable page

        
  	include("templates/footer.php");


This post has been edited by macosxnerd101: 26 February 2014 - 10:44 AM
Reason for edit:: Please use code tags

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1