CMS, PHP & MySQL, Demos, Tutorials

A few people have asked me for links for tutorials on making a cms or have asked me to write one, so I've put together a tutorial on making a cms from the very beginning. The cms will be really simple all it will consist of is pages that are completely database driven that you can edit existing pages and create new pages.

To get a better idea of what I'm taking about have a look at the demo to login to the admin you'll need the following details:

Username: admin
Password: admin

To access the admin section go to http://www.daveismyname.blog/simple-cms/admin

Before I do anything I like to put the structure together the following image shows all the files and folders. Notice the image folder is empty, to keep things simple I've not included any images as you'll be using your own images anyway. Also setup.php is not part of the system but a file containing the MySQL tables and sample data to get you started, simply copy and paste the code into your database using a database management tool such as phpmyadmin. 

Once I've set the structure it's time to create the config file every page calls this file so it makes sense to create this first. 

includes/config.php

First I turn on output buffering to enable the use of headers anywhere on the page and turn on sessions then provide the database connection details along with a connection, I use the error suppressor @ when connecting to the database then provide a custom error message in the event the connection attempt fails. 

Next I create some constants that will be used throughout the cms, DIR points to the address of the cms and DIRADMIN points to the admin part of the cms. I've also created a constant called included as a security measure so I can restrict access to files directly. You'll see this in action at the top of functions.php in a moment. Lastly I include functions.php as again this file will be needed throughout the project.

<?php
ob_start();
session_start();

// db properties
define('DBHOST','host');
define('DBUSER','database username');
define('DBPASS','password');
define('DBNAME','database name');

// make a connection to mysql here
$conn = @mysql_connect (DBHOST, DBUSER, DBPASS);
$conn = @mysql_select_db (DBNAME);
if(!$conn){
    die( "Sorry! There seems to be a problem connecting to our database.");
}

// define site path
define('DIR','http://www.domain.com/');

// define admin site path
define('DIRADMIN','http://www.domain.com/admin/');

// define site title for top of the browser
define('SITETITLE','Simple CMS');

//define include checker
define('included', 1);

include('functions.php');
?>

includes/functions.php

The first thing I do in this file is make sure it's been included otherwise throw an error by checking if the constant from includes/config.php has been defined. <
<p>

 if (!defined('included')){
    die('You cannot access this file directly!');
 }

Then I list all the functions the cms will use, namely:
  login                 = logs the user in
  logged_in         = returns true of false if logged in or not
  login_required  = checks if logged in if not redirects to login page
  logout               = logs the user out
  messages        = show any notifications
  errors               = shows any error

login requires 2 parameters, username and password, if then strips any tags and make them safe for database interaction using strip tags followed by mysql_real_escape_string. I encrypt passwords using an algorithm called md5 this is a one-way encryption.

Then the function checks the username and password in the members table if there is a match then set a session which can be used for other functions to check if a user is logged in. If there wasn't a match then show an error message.

//log user in ---------------------------------------------------
function login($user, $pass){

   //strip all tags from variable   
   $user = strip_tags(mysql_real_escape_string($user));
   $pass = strip_tags(mysql_real_escape_string($pass));

   $pass = md5($pass);

   // check if the user id and password combination exist in database
   $sql = "SELECT * FROM members WHERE username = '$user' AND password = '$pass'";
   $result = mysql_query($sql) or die('Query failed. ' . mysql_error());
      
   if (mysql_num_rows($result) == 1) {
      // the username and password match,
      // set the session
      $_SESSION['authorized'] = true;
                      
      // direct to admin
      header('Location: '.DIRADMIN);
      exit();
   } else {
    // define an error message
    $_SESSION['error'] = 'Sorry, wrong username or password';
   }
}

logged_in simply checks if the session authorized is equal to true, if so return true otherwise return false

function logged_in() {
    if($_SESSION['authorized'] == true) {
        return true;
    } else {
        return false;
    }    
}

login_required checks the outcome of logged_in (true or false) and if logged in returns true otherwise redirects user to login.

function login_required() {
    if(logged_in()) {    
        return true;
    } else {
        header('Location: '.DIRADMIN.'login.php');
        exit();
    }    
}

logout simply unsets the session and redirects the user.

function logout(){
    unset($_SESSION['authorized']);
    header('Location: '.DIRADMIN.'login.php');
    exit();
}

messages shows any messages stored in a session, once show clears the session

function messages() {
    $message = '';
    if($_SESSION['success'] != '') {
        $message = '<div class="msg-ok">'.$_SESSION['success'].'</div>';
        $_SESSION['success'] = '';
    }
    if($_SESSION['error'] != '') {
        $message = '<div class="msg-error">'.$_SESSION['error'].'</div>';
        $_SESSION['error'] = '';
    }
    echo "$message";
}

errors loops through all errors passed to it from an array and shows them to the user

function errors($error){
    if (!empty($error))
    {
            $i = 0;
            while ($i < count($error)){
            $showError.= "<div class="msg-error">".$error[$i]."</div>";
            $i ++;}
            echo $showError;
    }// close if empty errors
} // close function

index.php

This file controls everything on the front-end of the website. First include the config file then start the normal html for the title tag in the header of the html call the SITETITLE constant, then include the css file. I always use full paths so I include the DIR constant which stores the sites path then I can adjust the path as I need to. The great thing about doing things this way if I move the site I only need to update the config file.

For the navigation I manually place the home link ad this will always be first and always be present, then loop through all pages in the pages table that has a value of isRoot equal to 1 meaning it's not the home page and loop through all the records and create links for each page:

<ul class="menu">
    <li><a href="<?php echo DIR;?>">Home</a></li>    
    <?php
        //get the rest of the pages
        $sql = mysql_query("SELECT * FROM pages WHERE isRoot='1' ORDER BY pageID");
        while ($row = mysql_fetch_object($sql))
        {
            echo "<li><a href="".DIR."?p=$row->pageID">$row->pageTitle</a></li>"; 
        }
    ?>
    </ul>

For the pages content first check if a super global GET called p has been set if it has then a page has been requested in which case take the requested id and query the database with it and pull back the required page content, otherwise pull the record that has an pageID of 1. Next create an object of the result and print the page's content. 

<?php    
    //if no page clicked on load home page default to it of 1
    if(!isset($_GET['p'])){
        $q = mysql_query("SELECT * FROM pages WHERE pageID='1'");
    } else { //load requested page based on the id
        $id = $_GET['p']; //get the requested id
        $id = mysql_real_escape_string($id); //make it safe for database use
        $q = mysql_query("SELECT * FROM pages WHERE pageID='$id'");
    }
    
    //get page data from database and create an object
    $r = mysql_fetch_object($q);
    
    //print the pages content
    echo "<h1>$r->pageTitle</h2>";
    echo $r->pageCont;
    ?>

In it's simplest for that's all there is to the front end of the CMS, I told you it was very basic :) in the footer I've opted to put the site's title by using the constant SITETITLE and give the current year using the date function.

 <div class="copy">&copy; <?php echo SITETITLE.' '. date('Y');?> </div>

So that's the front end revealed now it's time to build the back-end to allow you to login and make changes.

admin/login.php

This page has it's own page markup so I can give it a different look to everywhere else, at the top of the file include the config as usual and then check if the user is already logged in, if they are redirect them

<?php require('../includes/config.php'); 
    if(logged_in()) {header('Location: '.DIRADMIN);}
    ?>

To login there needs to be a form for the user to fill out, the form only needs two fields the username and password. Above the form call the messages function to show any messages such as a failed login attempt.

 <p><?php echo messages();?></p>        
    <form method="post" action="">
    <p><label><strong>Username</strong><input type="text" name="username" /></label></p>
    <p><label><strong>Password</strong><input type="password" name="password" /></label></p>
    <p><br /><input type="submit" name="submit" class="button" value="login" /></p>                       
    </form>

If the form has been submitted then send the username and password to the login function:

 <?php 
        if($_POST['submit']) {
            login($_POST['username'], $_POST['password']);
        }
    ?>

admin/index.php

This page will lists all pages, allowing you to edit or delete as well as add new pages. Normally a cms admin panel would have far more options but I've chosen to have pages and nothing else to keep it as simple as possible.

Start off by including the config file and then forcing the user to login by calling the function login_required() if the user is not logged in they will b redirect to the login page, next check if a request to log out has been called and calling the logout function if needed.

Another important step check if a request to delete a page has been issued by checking if $_GET['delpage'] has been set if it has then process the pageID and delete the page set a message session then reload the page. Deleting a page will only happen when a javascript call has been made and a popup confirmation appears and yes is clicked on.

<?php require('../includes/config.php'); 

//make sure user is logged in, function will redirect use if not logged in
login_required();

//if logout has been clicked run the logout function which will destroy any active sessions and redirect to the login page
if(isset($_GET['logout'])){
    logout();
}

//run if a page deletion has been requested
if(isset($_GET['delpage'])){
        
    $delpage = $_GET['delpage'];
    $delpage = mysql_real_escape_string($delpage);
    $sql = mysql_query("DELETE FROM pages WHERE pageID = '$delpage'");
    $_SESSION['success'] = "Page Deleted"; 
    header('Location: ' .DIRADMIN);
       exit();
}

?>

Next list the normal html, title, css files etc inside the head tags we need to place a javascript function to delete a page it will accept two parameters the pageID and title, the function when called create a popup conformation box with two options yes or no is yes is clicked then the window.location.href is activated. if no is clicked the box closes and nothing happens.

<script language="JavaScript" type="text/javascript">
    function delpage(id, title)
    {
       if (confirm("Are you sure you want to delete '" + title + "'"))
       {
          window.location.href = '<?php echo DIRADMIN;?>?delpage=' + id;
       }
    }
</script>

For the navigation I have three static links, a link for the main admin, a link to view the front-end and logout, notice the path for logout is the siteadmin path followed by ?logout this is used to call the logout function.

<div id="navigation">
    <ul class="menu">
        <li><a href="<?php echo DIRADMIN;?>">Admin</a></li>        
        <li><a href="<?php echo DIR;?>" target="_blank">View Website</a></li>
        <li><a href="<?php echo DIRADMIN;?>?logout">Logout</a></li>
    </ul>
</div>

Next create a table that will list all pages from the pages table, notice we're checking the pageID for a '1' if found remove the delete link to make sure you can't delete the home page by mistake (it does happen). The edit link uses the DIRADMIN constant followed by editpage.php?id the next bit passes the pageID to the link which will be used when editing a page so the link know's which page you're requesting.

The delete link uses a javascript call to call the javascript function we call earlier it requires the page id and title.

<table>
<tr>
    <th><strong>Title</strong></th>
    <th><strong>Action</strong></th>
</tr>

<?php
$sql = mysql_query("SELECT * FROM pages ORDER BY pageID");
while($row = mysql_fetch_object($sql)) 
{
    echo "<tr>";
        echo "<td>$row->pageTitle</td>";
        if($row->pageID == 1){ //home page hide the delete link
            echo "<td><a href="".DIRADMIN."editpage.php?id=$row->pageID">Edit</a></td>";
        } else {
            echo "<td><a href="".DIRADMIN."editpage.php?id=$row->pageID">Edit</a> | <a href="javascript:delpage('$row->pageID','$row->pageTitle');">Delete</a></td>";
        }
        
    echo "</tr>";
}
?>
</table>

After the form I've set a link to create new pages.

<p><a href="<?php echo DIRADMIN;?>addpage.php" class="button">Add Page</a></p>

admin/addpage.php

This page is used to create a new page, it's very simple there's a form that needs a title and the content you're would like, the content textarea is a plain box so any html markup will need to be entered there, to make life easier it's recommended to use an editor my editor of choice is tinyMCE http://tinymce.moxiecode.com it's simple to use and very powerful, for the sake of simplicity I've not used an editor in the tutorial but including tinyMCE is just a case of including the files and placing a piece of javascript in the header of the file.

Here's the form I'll be using notice the title input has a name of pageTitle this is important as the name will become a php variable so the data can be captured when submitted and put into the database, the same goes for pageCont.

<form action="" method="post">
<p>Title:<br /> <input name="pageTitle" type="text" value="" size="103" /></p>
<p>content<br /><textarea name="pageCont" cols="100" rows="20"></textarea></p>
<p><input type="submit" name="submit" value="Submit" class="button" /></p>
</form>

Processing the form is very simple check if the form has been submitted and if it has then get the data from the form, make it safe for database entry then using mysql_query insert a new record in the database. Finally add a message to a session and redirect to the main admin page.

if(isset($_POST['submit'])){

    $title = $_POST['pageTitle'];
    $content = $_POST['pageCont'];
    
    $title = mysql_real_escape_string($title);
    $content = mysql_real_escape_string($content);
    
    mysql_query("INSERT INTO pages (pageTitle,pageCont) VALUES ('$title','$content')")or die(mysql_error());
    $_SESSION['success'] = 'Page Added';
    header('Location: '.DIRADMIN);
    exit();

}

admin/editpage.php

This page is very similar to the add page, with a few additions the first of which is a check to make sure a pageID has been passed to this page if not redirect the user

if(!isset($_GET['id']) || $_GET['id'] == ''){ //if no id is passed to this page take user back to previous page
    header('Location: '.DIRADMIN); 
}

To update the content we'll need a form with the pages content there for us to edit to do this we query the database and pass the requested page id and create an object to we can then fill the form with the values from the database.

<?php
$id = $_GET['id'];
$id = mysql_real_escape_string($id);
$q = mysql_query("SELECT * FROM pages WHERE pageID='$id'");
$row = mysql_fetch_object($q);
?>

<form action="" method="post">
<input type="hidden" name="pageID" value="<?php echo $row->pageID;?>" />
<p>Title:<br /> <input name="pageTitle" type="text" value="<?php echo $row->pageTitle;?>" size="103" />
</p>
<p>content<br /><textarea name="pageCont" cols="100" rows="20"><?php echo $row->pageCont;?></textarea>
</p>
<p><input type="submit" name="submit" value="Submit" class="button" /></p>
</form>

Processing the updated form is almost the same as adding a new one the only difference is there's a hidden input in the form called pageID which is the id of the page and the mysql_query instead of inserting data it will update it so we need to update accordingly:

if(isset($_POST['submit'])){

    $title = $_POST['pageTitle'];
    $content = $_POST['pageCont'];
    $pageID = $_POST['pageID'];
    
    $title = mysql_real_escape_string($title);
    $content = mysql_real_escape_string($content);
    
    mysql_query("UPDATE pages SET pageTitle='$title', pageCont='$content' WHERE pageID='$pageID'");
    $_SESSION['success'] = 'Page Updated';
    header('Location: '.DIRADMIN);
    exit();

}

That's all the files for the cms it's very simple but will give you a starting point on making your own cms, there are many things that can be improved upon, for clarity here's all the files listed.

includes/config.php

<?php
ob_start();
session_start();

// db properties
define('DBHOST','host');
define('DBUSER','database username');
define('DBPASS','password');
define('DBNAME','database name');

// make a connection to mysql here
$conn = @mysql_connect (DBHOST, DBUSER, DBPASS);
$conn = @mysql_select_db (DBNAME);
if(!$conn){
    die( "Sorry! There seems to be a problem connecting to our database.");
}

// define site path
define('DIR','http://www.domain.com/');

// define admin site path
define('DIRADMIN','http://www.domain.com/admin/');

// define site title for top of the browser
define('SITETITLE','Simple CMS');

//define include checker
define('included', 1);

include('functions.php');
?>

includes/functions.php

<?php

if (!defined('included')){
die('You cannot access this file directly!');
}

//log user in ---------------------------------------------------
function login($user, $pass){

   //strip all tags from varible   
   $user = strip_tags(mysql_real_escape_string($user));
   $pass = strip_tags(mysql_real_escape_string($pass));

   $pass = md5($pass);

   // check if the user id and password combination exist in database
   $sql = "SELECT * FROM members WHERE username = '$user' AND password = '$pass'";
   $result = mysql_query($sql) or die('Query failed. ' . mysql_error());
      
   if (mysql_num_rows($result) == 1) {
      // the username and password match,
      // set the session
      $_SESSION['authorized'] = true;
                      
      // direct to admin
      header('Location: '.DIRADMIN);
      exit();
   } else {
    // define an error message
    $_SESSION['error'] = 'Sorry, wrong username or password';
   }
}

// Authentication
function logged_in() {
    if($_SESSION['authorized'] == true) {
        return true;
    } else {
        return false;
    }    
}

function login_required() {
    if(logged_in()) {    
        return true;
    } else {
        header('Location: '.DIRADMIN.'login.php');
        exit();
    }    
}

function logout(){
    unset($_SESSION['authorized']);
    header('Location: '.DIRADMIN.'login.php');
    exit();
}

// Render error messages
function messages() {
    $message = '';
    if($_SESSION['success'] != '') {
        $message = '<div class="msg-ok">'.$_SESSION['success'].'</div>';
        $_SESSION['success'] = '';
    }
    if($_SESSION['error'] != '') {
        $message = '<div class="msg-error">'.$_SESSION['error'].'</div>';
        $_SESSION['error'] = '';
    }
    echo "$message";
}

function errors($error){
    if (!empty($error))
    {
            $i = 0;
            while ($i < count($error)){
            $showError.= "<div class="msg-error">".$error[$i]."</div>";
            $i ++;}
            echo $showError;
    }// close if empty errors
} // close function

?>

admin/login.php

<?php require('../includes/config.php'); 
if(logged_in()) {header('Location: '.DIRADMIN);}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title><?php echo SITETITLE;?></title>
<link rel="stylesheet" href="<?php echo DIR;?>style/login.css" type="text/css" />
</head>
<body>
<div class="lwidth">
    <div class="page-wrap">
        <div class="content">
        
        <?php 
        if($_POST['submit']) {
            login($_POST['username'], $_POST['password']);
        }
        ?>

<div id="login">
    <p><?php echo messages();?></p>        
    <form method="post" action="">
    <p><label><strong>Username</strong><input type="text" name="username" /></label></p>
    <p><label><strong>Password</strong><input type="password" name="password" /></label></p>
    <p><br /><input type="submit" name="submit" class="button" value="login" /></p>                       
    </form>            
</div>
        
        </div>    
        <div class="clear"></div>        
    </div>
<div class="footer">&copy; <?php echo SITETITLE.' '. date('Y');?> </div>    
</div>
</body>
</html>
</pre>

<p>admin/index.php</p>
<pre lang="php">
<?php require('../includes/config.php'); 

//make sure user is logged in, function will redirect use if not logged in
login_required();

//if logout has been clicked run the logout function which will destroy any active sessions and redirect to the login page
if(isset($_GET['logout'])){
    logout();
}

//run if a page deletion has been requested
if(isset($_GET['delpage'])){
        
    $delpage = $_GET['delpage'];
    $delpage = mysql_real_escape_string($delpage);
    $sql = mysql_query("DELETE FROM pages WHERE pageID = '$delpage'");
    $_SESSION['success'] = "Page Deleted"; 
    header('Location: ' .DIRADMIN);
       exit();
}

?>
<!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" />
<title><?php echo SITETITLE;?></title>
<link href="<?php echo DIR;?>style/style.css" rel="stylesheet" type="text/css" />
<script language="JavaScript" type="text/javascript">
    function delpage(id, title)
    {
       if (confirm("Are you sure you want to delete '" + title + "'"))
       {
          window.location.href = '<?php echo DIRADMIN;?>?delpage=' + id;
       }
    }
</script>
</head>
<body>

<div id="wrapper">

<div id="logo"><a href="<?php echo DIRADMIN;?>"><img src="images/logo.png" alt="<?php echo SITETITLE;?>" border="0" /></a></div>

<!-- NAV -->
<div id="navigation">
    <ul class="menu">
        <li><a href="<?php echo DIRADMIN;?>">Admin</a></li>        
        <li><a href="<?php echo DIR;?>" target="_blank">View Website</a></li>
        <li><a href="<?php echo DIRADMIN;?>?logout">Logout</a></li>
    </ul>
</div>
<!-- END NAV -->

<div id="content">

<?php 
    //show any messages if there are any.
    messages();
?>

<h1>Manage Pages</h1>

<table>
<tr>
    <th><strong>Title</strong></th>
    <th><strong>Action</strong></th>
</tr>

<?php
$sql = mysql_query("SELECT * FROM pages ORDER BY pageID");
while($row = mysql_fetch_object($sql)) 
{
    echo "<tr>";
        echo "<td>$row->pageTitle</td>";
        if($row->pageID == 1){ //home page hide the delete link
            echo "<td><a href="".DIRADMIN."editpage.php?id=$row->pageID">Edit</a></td>";
        } else {
            echo "<td><a href="".DIRADMIN."editpage.php?id=$row->pageID">Edit</a> | <a href="javascript:delpage('$row->pageID','$row->pageTitle');">Delete</a></td>";
        }
        
    echo "</tr>";
}
?>
</table>

<p><a href="<?php echo DIRADMIN;?>addpage.php" class="button">Add Page</a></p>
</div>

<div id="footer">    
        <div class="copy">&copy; <?php echo SITETITLE.' '. date('Y');?> </div>
</div><!-- close footer -->
</div><!-- close wrapper -->

</body>
</html>

admin/addpage.php

<?php require('../includes/config.php'); 

if(isset($_POST['submit'])){

    $title = $_POST['pageTitle'];
    $content = $_POST['pageCont'];
    
    $title = mysql_real_escape_string($title);
    $content = mysql_real_escape_string($content);
    
    mysql_query("INSERT INTO pages (pageTitle,pageCont) VALUES ('$title','$content')")or die(mysql_error());
    $_SESSION['success'] = 'Page Added';
    header('Location: '.DIRADMIN);
    exit();

}

?>
<!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" />
<title><?php echo SITETITLE;?></title>
<link href="<?php echo DIR;?>style/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="wrapper">

<div id="logo"><a href="<?php echo DIR;?>"><img src="images/logo.png" alt="<?php echo SITETITLE;?>" title="<?php echo SITETITLE;?>" border="0" /></a></div><!-- close logo -->

<!-- NAV -->
<div id="navigation">
<ul class="menu">
<li><a href="<?php echo DIRADMIN;?>">Admin</a></li>
<li><a href="<?php echo DIRADMIN;?>?logout">Logout</a></li>
<li><a href="<?php echo DIR;?>" target="_blank">View Website</a></li>
</ul>
</div>
<!-- END NAV -->

<div id="content">

<h1>Add Page</h1>

<form action="" method="post">
<p>Title:<br /> <input name="pageTitle" type="text" value="" size="103" /></p>
<p>content<br /><textarea name="pageCont" cols="100" rows="20"></textarea></p>
<p><input type="submit" name="submit" value="Submit" class="button" /></p>
</form>

</div>

<div id="footer">    
        <div class="copy">&copy; <?php echo SITETITLE.' '. date('Y');?> </div>
</div><!-- close footer -->
</div><!-- close wrapper -->

</body>
</html>
</pre>

<p>admin/editpage.php</p>
<pre lang="php">
<?php require('../includes/config.php'); 

if(!isset($_GET['id']) || $_GET['id'] == ''){ //if no id is passed to this page take user back to previous page
    header('Location: '.DIRADMIN); 
}

if(isset($_POST['submit'])){

    $title = $_POST['pageTitle'];
    $content = $_POST['pageCont'];
    $pageID = $_POST['pageID'];
    
    $title = mysql_real_escape_string($title);
    $content = mysql_real_escape_string($content);
    
    mysql_query("UPDATE pages SET pageTitle='$title', pageCont='$content' WHERE pageID='$pageID'");
    $_SESSION['success'] = 'Page Updated';
    header('Location: '.DIRADMIN);
    exit();

}

?>
<!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" />
<title><?php echo SITETITLE;?></title>
<link href="<?php echo DIR;?>style/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="wrapper">

<div id="logo"><a href="<?php echo DIR;?>"><img src="images/logo.png" alt="<?php echo SITETITLE;?>" title="<?php echo SITETITLE;?>" border="0" /></a></div><!-- close logo -->

<!-- NAV -->
<div id="navigation">
<ul class="menu">
<li><a href="<?php echo DIRADMIN;?>">Admin</a></li>
<li><a href="<?php echo DIRADMIN;?>?logout">Logout</a></li>
<li><a href="<?php echo DIR;?>" target="_blank">View Website</a></li>
</ul>
</div>
<!-- END NAV -->

<div id="content">

<h1>Edit Page</h1>

<?php
$id = $_GET['id'];
$id = mysql_real_escape_string($id);
$q = mysql_query("SELECT * FROM pages WHERE pageID='$id'");
$row = mysql_fetch_object($q);
?>


<form action="" method="post">
<input type="hidden" name="pageID" value="<?php echo $row->pageID;?>" />
<p>Title:<br /> <input name="pageTitle" type="text" value="<?php echo $row->pageTitle;?>" size="103" />
</p>
<p>content<br /><textarea name="pageCont" cols="100" rows="20"><?php echo $row->pageCont;?></textarea>
</p>
<p><input type="submit" name="submit" value="Submit" class="button" /></p>
</form>

</div>

<div id="footer">    
        <div class="copy">&copy; <?php echo SITETITLE.' '. date('Y');?> </div>
</div><!-- close footer -->
</div><!-- close wrapper -->

</body>
</html>
</pre>

<p>index.php</p>
<pre lang="php">
<?php require('includes/config.php'); ?>
<!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" />
<title><?php echo SITETITLE;?></title>
<link href="<?php echo DIR;?>style/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="wrapper">

    <div id="logo"><a href="<?php echo DIR;?>"><img src="images/logo.png" alt="<?php echo SITETITLE;?>" title="<?php echo SITETITLE;?>" border="0" /></a></div><!-- close logo -->
    
    <!-- NAV -->
    <div id="navigation">
    <ul class="menu">
    <li><a href="<?php echo DIR;?>">Home</a></li>
    <?php
        //get the rest of the pages
        $sql = mysql_query("SELECT * FROM pages WHERE isRoot='1' ORDER BY pageID");
        while ($row = mysql_fetch_object($sql))
        {
            echo "<li><a href="".DIR."?p=$row->pageID">$row->pageTitle</a></li>"; 
        }
    ?>
    </ul>
    </div>
    <!-- END NAV -->
    
    <div id="content">
    
    <?php    
    //if no page clicked on load home page default to it of 1
    if(!isset($_GET['p'])){
        $q = mysql_query("SELECT * FROM pages WHERE pageID='1'");
    } else { //load requested page based on the id
        $id = $_GET['p']; //get the requested id
        $id = mysql_real_escape_string($id); //make it safe for database use
        $q = mysql_query("SELECT * FROM pages WHERE pageID='$id'");
    }
    
    //get page data from database and create an object
    $r = mysql_fetch_object($q);
    
    //print the pages content
    echo "<h1>$r->pageTitle</h2>";
    echo $r->pageCont;
    ?>
    
    </div><!-- close content div -->

    <div id="footer">    
            <div class="copy">&copy; <?php echo SITETITLE.' '. date('Y');?> </div>
    </div><!-- close footer -->
</div><!-- close wrapper -->

</body>
</html>

setup.php

CREATE TABLE IF NOT EXISTS `members` (
  `memberID` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL DEFAULT '',
  `password` varchar(32) NOT NULL DEFAULT '',
  PRIMARY KEY (`memberID`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;

INSERT INTO `members` (`memberID`, `username`, `password`) VALUES
(1, 'admin', '21232f297a57a5a743894a0e4a801fc3');

CREATE TABLE IF NOT EXISTS `pages` (
  `pageID` int(11) NOT NULL AUTO_INCREMENT,
  `pageTitle` varchar(255) DEFAULT NULL,
  `isRoot` int(11) NOT NULL DEFAULT '1',
  `pageCont` text,
  PRIMARY KEY (`pageID`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

INSERT INTO `pages` (`pageID`, `pageTitle`, `isRoot`, `pageCont`) VALUES
(1, 'Home', 0, '<p>Sample Sample content</p>'),
(2, 'About', 1, '<p>Sample Sample content</p>'),
(3, 'Services', 1, '<p>Sample Sample content</p>'),
(4, 'News', 1, '<p>Sample Sample content</p>'),
(5, 'Contact', 1, '<p>Sample Sample content</p>');

I hope you've found this tutorial useful any comments, suggestions are always welcomed.