Page 1 of 2

[PHP] Dynamic website

Posted: Wed Sep 30, 2009 8:55 pm
by Chris
Hi, I thought I'd write a little tutorial. This topic is something that I come across quite a lot. People asking how can I make my website more dynamic.

I notice quite a lot of people make a PHP script. The script is usually including the header and the navigation. They then go on and use this script to make a new one, then make another and keep going on until there are so many scripts that when they want to maybe update them all easily, like say include another file on every page. They have to edit around 50 scripts.

This is a small sight into my solution to this problem. I have my own complicated way of doing it basically because I find it easier to work with and I find it helps keep my sites more secure. But in this tutorial I will cover some basics to show you some methods of easily implementing scripts and functions on one page.

Here we go.

First of all we want to create a PHP page with some basic HTML divs to make up the structure of the website. This will be the index page and will include every script you make. I'll start with a simple header, error, success and content div.

Code: Select all

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>

    <body>
        <div id="header">
            <h1>Website Header</h1>
        </div>

        <div id="success">
        </div>

        <div id="error">
        </div>

        <div id="content">
        </div>

    </body>
</html>
  
So very nice. We've managed to write some XHTML. What's next?

Next comes some PHP :D. We are going to set up some arrays which will be used by every script you make to enable the "message" and the "content" divs. This will go at the top of the HTML. on line 1.

Code: Select all

<?php

    // content array
    $con = array(    'switch' => true,
                    'content' => "" ); // content will be a string. It will contain the main html of each script.

    // error array
    $err = array(    'switch' => false,
                    'message' => array() ); // We will loop through the message arrays to show any errors, or successes in each array

    // success array
    $suc  = array(    'switch' => false,
                    'message' => array() );

?>
Okay very good. We have set up some arrays. You might be wondering what the hell these are for. It will all come clear soon enough.

Here we go. Lets go have a look at our HTML again.

We're going to set it so if that the content, error and success divs will only be shown if the switch in the array is set to true. To do this we will need to add some PHP in our HTML. We'll also make some loops to loop through the successes and errors.
Replace this

Code: Select all

<div id="success">
</div>

<div id="error">
</div>

<div id="content">
</div>
 
with this

Code: Select all

<?php

// Successes
if( $suc['switch'] == true )
{
    echo "<div id=\"success\">
        Success
        <ul>\n";

    foreach( $suc['message'] as $success )
    {
        echo "<li>$success</li>\n";
    }
    echo "</div>\n";
}

// Errors
if( $err['switch'] == true )
{
    echo "<div id=\"error\">
        Error
        <ul>\n";

    foreach( $err['message'] as $error )
    {
        echo "<li>$error</li>\n";
    }
    echo "</div>\n";
}

// Successes
if( $con['switch'] == true )
{
    echo "
    <div id=\"content\">
        {$con['content']}
    </div>\n";
}
?>
Finally, go roll a joint and have some hamburgers, We have the main skeleton made! Now lets get to the fun stuff. Including some scripts.

Back to the PHP we made earlier.

Under the arrays we made, we are going to start writing some code that will open a file depending on what is in the query string. the key in the query string will be 'page'. These scripts will all be saved in the "scripts" directory, so go on ahead and make that aswell.
Lets get started.

Code: Select all

<?php 
// first check what page needs to be included. If it's null. We'll set it to home.php
if( empty($_GET['page']) )
{
    $_GET['page'] = "home";
}

// added this after Falken pointed out a security loop
// check if the file exists in the scripts folder
if( !in_array("{$_GET['page']}.php", scandir("scripts")) && $_GET['page'] != "." && $_GET['page'] != ".."  )
{
    // If it exists, include the script
    include("scripts/{$_GET['page']}.php");
}
else
{
    // If it doesn't exist. We can turn the content div off. And make the error div have an error
    $err['message'][] = "404 file not found.";
    $con['switch'] = false;
    $err['switch'] = true;
}
  
Yay, "scripts/home.php" doesn't exist! This mean if you know run your script you should be getting a page with a big header containing "Website Header" and a list containg "404 file not found."

Lets go make the home page.
This is the last step of the tutorial.
In this bit I will show you the use of enebling the error and success divs, aswell as ad some content to the page. Here we go
Save this as "home.php", in the "scripts" directory.

Code: Select all

<?php

// if something has been posted, do some fancy stuff
if( $_SERVER['REQUEST_METHOD'] == "POST" )
{
    if( isset($_POST['box1']) )
    {
        $suc['switch'] = true;
        $suc['message'][] = "You checked the first box giving this success message";
    }
    if( isset($_POST['box2']) )
    {
        $err['switch'] = true;
        $err['message'][] = "You checked the second box giving this error message";
    }
    if( isset($_POST['box3']) )
    {
        $err['switch'] = true;
        $err['message'][] = "Uh OH! You checked the third box. <a href=\"{$_SERVER['PHP_SELF']}?page=home\">Click here to go back</a>";
        $suc['switch'] = true;
        $suc['message'][] = "You checked the third box giving this success message and turning off the content";
        $con['switch'] = false;
    }
}

$con['content'] = "
<form action=\"{$_SERVER['PHP_SELF']}?page=home\" method=\"post\">
    <input type=\"checkbox\" name=\"box1\" value=\"true\" />Check this box to show a success message<br />
    <input type=\"checkbox\" name=\"box2\" value=\"true\" />Check this box to show an error message<br />
    <input type=\"checkbox\" name=\"box3\" value=\"true\" />Check this box to show a succes messages an error message and turn off the content<br />
    <input type=\"submit\" name=\"submit\" value=\"submit\" />
</form>\n";

?>



[line]
Here are the results
index.php

Code: Select all

<?php

    // content array
    $con = array(    'switch' => true,
                    'content' => "" ); // content will be a string. It will contain the main html of each script.

    // error array
    $err = array(    'switch' => false,
                    'message' => array() ); // We will loop through the message arrays to show any errors, or successes in each array

    // success array
    $suc  = array(    'switch' => false,
                    'message' => array() );

    // first check what page needs to be included. If it's null. We'll set it to home.php
    if( empty($_GET['page']) )
    {
        $_GET['page'] = "home";
    }
    
    // added this after Falken pointed out a security loop
    // check if the file exists in the scripts folder
    if( in_array("{$_GET['page']}.php", scandir("scripts")) && $_GET['page'] != "." && $_GET['page'] != ".." )
    {
        // If it exists, include the script
        include("scripts/{$_GET['page']}.php");
    }
    else
    {
        // If it doesn't exist. We can turn the content div off. And make the error div have an error
        $err['message'][] = "404 file not found.";
        $con['switch'] = false;
        $err['switch'] = true;
    }
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>

    <body>

    <div id="header">
        <h1>Website Header</h1>
    </div>

    <?php
    
    // Successes
    if( $suc['switch'] == true )
    {
        echo "<div id=\"success\">
            Success
            <ul>\n";
    
        foreach( $suc['message'] as $success )
        {
            echo "<li>$success</li>\n";
        }
        echo "</div>\n";
    }
    
    // Errors
    if( $err['switch'] == true )
    {
        echo "<div id=\"error\">
            Error
            <ul>\n";
    
        foreach( $err['message'] as $error )
        {
            echo "<li>$error</li>\n";
        }
        echo "</div>\n";
    }
    
    // Successes
    if( $con['switch'] == true )
    {
        echo "
        <div id=\"content\">
            {$con['content']}
        </div>\n";
    }
    ?>
    </body>
</html>
scripts/home.php

Code: Select all

<?php

// if something has been posted, do some fancy stuff
if( $_SERVER['REQUEST_METHOD'] == "POST" )
{
    if( isset($_POST['box1']) )
    {
        $suc['switch'] = true;
        $suc['message'][] = "You checked the first box giving this success message";
    }
    if( isset($_POST['box2']) )
    {
        $err['switch'] = true;
        $err['message'][] = "You checked the second box giving this error message";
    }
    if( isset($_POST['box3']) )
    {
        $err['switch'] = true;
        $err['message'][] = "Uh OH! You checked the third box. <a href=\"{$_SERVER['PHP_SELF']}?page=home\">Click here to go back</a>";
        $suc['switch'] = true;
        $suc['message'][] = "You checked the third box giving this success message and turning off the content";
        $con['switch'] = false;
    }
}

$con['content'] = "
<form action=\"{$_SERVER['PHP_SELF']}?page=home\" method=\"post\">
    <input type=\"checkbox\" name=\"box1\" value=\"true\" />Check this box to show a success message<br />
    <input type=\"checkbox\" name=\"box2\" value=\"true\" />Check this box to show an error message<br />
    <input type=\"checkbox\" name=\"box3\" value=\"true\" />Check this box to show a succes messages an error message and turn off the content<br />
    <input type=\"submit\" name=\"submit\" value=\"submit\" />
</form>\n";

?>
I hope that explains a lot and will help you guys make your sites more dynamic,
Chris

I updates the file_exists function with a lazy in_array function using scandir to read the directory for a security problem Falken pointed out. This function is only available in PHP 5+
http://us2.php.net/manual/en/function.scandir.php
if you aren't using PHP 5 you could also use something like this

Code: Select all

<?php 
if( $handle = @opendir('scripts') )
{
    while( false !== ($file = readdir($handle)) )
    {
        if( $file != "." && $file != ".." )
        {
            if( $file == "{$_GET['page']}.php" )
            {
                include("scripts/$file");
                $fileFound = true;
            }
        }
    }
    closedir($handle);
}

if( empty($fileFound) )
{
    // If it doesn't exist. We can turn the content div off. And make the error div have an error
    $err['message'][] = "404 file not found.";
    $con['switch'] = false;
    $err['switch'] = true;
}
  
Here's a live demo:
http://chrishemmens.net/tutorials/

Re: [PHP] Dynamic website

Posted: Wed Sep 30, 2009 8:57 pm
by D3luxe
Wow, nice second post. Should be very helpful to some of the web devs here.

Nice!

Re: [PHP] Dynamic website

Posted: Wed Sep 30, 2009 9:08 pm
by Chris
D3luxe wrote:Wow, nice second post. Should be very helpful to some of the web devs here.

Nice!
You replied quick! Didn't even have a chance to test it. Hope it's useful I spent an hour writing it.

Re: [PHP] Dynamic website

Posted: Wed Sep 30, 2009 10:31 pm
by hallsofvallhalla
this is very nice. Thank you for this.

Re: [PHP] Dynamic website

Posted: Wed Sep 30, 2009 11:22 pm
by Sakar
Nice tut! I was wondering about doing this sort of thing this morning. Will definitely help me out.

Re: [PHP] Dynamic website

Posted: Thu Oct 01, 2009 3:31 pm
by Falken
Read it and a good start tutorial for beginners. Altho I would like to point out a big security issue in your code.

At this part:

Code: Select all

if( @file_exists("scripts/{$_GET['page']}.php") )
{
    // If it does exist. Include the script.
    include("scripts/{$_GET['page']}.php");
}
This means they could simply put "index.php?page=../admin/secret.php" for example.

Altho there are 2 easy fixes to this:
- Put all the includable pages in their own folder, and then remove all "../" and "/" in the $_GET['page'] string.
- Or the best solution, put all valid pages in an array, and then check if $_GET['page'] exists somewhere in the array.

Can be good to know ;)

Re: [PHP] Dynamic website

Posted: Thu Oct 01, 2009 7:35 pm
by Chris
Yeah, the tutorial wasn't made to be secure. It was just to introduce the fact of rather than letting the scripts include the main files. Let the main file include the scripts. But it's good that you pointed it out.

Re: [PHP] Dynamic website

Posted: Thu Oct 01, 2009 8:08 pm
by Falken
Chris wrote:Yeah, the tutorial wasn't made to be secure. It was just to introduce the fact of rather than letting the scripts include the main files. Let the main file include the scripts. But it's good that you pointed it out.
Ye, I understand that, and it was good tutorial, but always good to make people aware of it atleast :)

Re: [PHP] Dynamic website

Posted: Thu Oct 01, 2009 8:52 pm
by Chris
I updated it. That will keep everyone happy ;).

Re: [PHP] Dynamic website

Posted: Thu Mar 24, 2011 6:55 pm
by My axe was stolen
If I were to use this with Hall's mmo tutorial how would I do the URLs for the equipment and backpack pages?

Right now it is as follows:

Code: Select all

echo "<a href='equipment.php?equip=1'>Equipment<br></a>";
echo "<a href='equipment.php?backpack=1'>Inventory</a><br>";
But that, obviously, doesn't work.

Thanks in advance. :)