Build your own CMS

We have all faced the situation where we had to build a small website with only a few pages where all pages look similar and feature the same header, menu and footer. In this tutorial I'm going to show you a way to save time building such websites, increase reuse and ease maintanability.

1. The basics

Sometimes, using a CMS like Joomla!, Dupal or even Wordpress is just too much for a certain job. You know that the client will never bother learning how to handle the back-end and that they will never venture to edit the site content on their own. Well, in this cases it's much more simple to leave those high-end CMS scripts aside and use a simple solution that will fit the bill.

For these cases, a server side programing language, like PHP, seems like the ideal solution. Why? Because of one of its key features: include statements.

Include statements are simple directives that would allow you to insert pre-defined code blocks into a parent file thus making possible to patch a file together using different code blocks.

2. The tools

We are going to use a server side programming language so we will also need a server to run our files on. While you could use your online server for this, in most cases it will be much more efficient to use a local server, installed on your own computer.

The easiest way to install a local server, would be to grab a pre-configured package like <a href="http://www.apachefriends.org/en/xampp.html" target="_blank">XAMPP</a>. It contains everything you need so yo won't have to bother installing each component separately.

3. Building the framework

In our example, we will be working on a simple website containing a logo, top menu, header and footer that will stay the same on all the pages. Additionally, there will be a content area that will change from page to page.

Here is our Photoshop mockup showing us how the final page will look like:

Photoshop Mockup

3.1 Creating the index file

No matter how simple or complex, a website must always contain an index file so let us start by creating it. Open your favourite code editor (a simple text editor would do) and create a new file called index.php. For now, this file will only contain the basic HTML markup:

<!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" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<meta name="resource-type" content="document" />
<meta name="revisit-after" content="10" />
<meta name="classification" content="Tutorials" />
<meta name="keywords" content="tutorials, nettuts, framework, php" />
<meta name="description" content="Tutorial - Build your own PHP CMS" />
<meta name="robots" content="ALL" />
<meta name="distribution" content="Global" />
<meta name="rating" content="Safe For Kids" />
<title>Lorem Components</title>
<link type="text/css" rel="stylesheet" rev="stylesheet" media="screen" href="css/main.css"  />
</head>

<body>
	<div id="container">

	</div>
</body>
</html>

As you can see, the page will be XHTML 1.0 Strict and will use a CSS stylesheet called main.css, located in a sub-folder called CSS. Finally, there is a div with the ID "container" that will include all page elements.

3.2 Creating the page blocks

Next we are going to concentrate on the page structure in order to identify its main blocks and areas. As you can easily see, the page can be divided in the following sections:

Except for the content area, the other blocks will stay the same on all the pages so we are going to create a separate file for each of these areas. These files will be the previously mentioned blocks that you will be using to build the website.

Switch back to your editor and create the following empty files:

The content of these files will be regular HTML markup for now so I'm not going to spend too much time on this as this is not the main topic of this tutorial. The files will contain the following lines:

logo.php

<!-- Create the logo stripe -->
<div id="logo">
	<h1>Lorem Components</h1>
</div>

navigation.php

<!-- Create the top menu/navigation -->
<div id="navigation">
	<ul>
		<li><a href="">Home</a></li>
		<li><a href="">About us</a></li>
		<li><a href="">Products</a></li>
		<li><a href="">Licensing</a></li>
		<li><a href="">Contact us</a></li>
	</ul>
</div>

banner.php

<!-- Create the banner -->
<div id="banner">
	<img src="images/banner_package.jpg" alt="Lorem Components - Gold Edition" title="Lorem Components - Gold Edition" width="260" height="260" />
	<div class="banner_text">
		<h1>Lorem Components - Gold Edition</h1>
		<p>Quisque tincidunt eros et lectus. Duis a velit id turpis dapibus consectetuer. In pellentesque erat nec eros. Donec nonummy, neque a facilisis adipiscing, urna libero facilisis ligula.</p>
		<ul>
			<li>- Duis a velit</li>
			<li>- Dapibus consectetur</li>
			<li>- Pellentesque erat</li>
			<li>- Donec nonummo</li>
			<li>- Quisque tincidunt</li>
			<li>- Libero facilis</li>
		</ul>
	</div>
</div>

footer.php

<div id="footer">
	<p>Copyright © <?php echo date("Y"); ?> - <a href="">yoursite.com</a></p>
	
	<ul>
		<li><a href="">Home</a></li>
		<li>|</li>
		<li><a href="">About us</a></li>
		<li>|</li>
		<li><a href="">Products</a></li>
		<li>|</li>
		<li><a href="">Contact us</a></li>
		<li>|</li>
		<li><a href="">Terms of use</a></li>
		<li>|</li>
		<li><a href="">Privacy policy</a></li>
	</ul>
</div>

One thing to mention is that, for now, all the links are empty. We will define these later, don't worry!

To keep the whole thing tidy, let's move all the php files except of index.php, to a folder called "pages".

Finally, we are going to create a block for the dynamic content area. This block would be for the home page so let's named it home.php. Put the following code inside:

<div id="home">
	<div id="home_welcome">
		<h1>Welcome to Lorem Designs</h1>
		<p>Quisque tincidunt eros et lectus. Duis a velit id turpis dapibus consectetuer. In pellentesque erat nec eros. Donec nonummy, neque a facilisis adipiscing, urna libero facilisis ligula, non consequat felis purus eu ante. Sed vitae turpis vitae quam varius rutrum. Phasellus vehicula. Nulla viverra. Sed sed nulla eu lectus consectetuer gravida. Praesent at metus. Maecenas eget justo at tortor auctor pretium. Integer sit amet nunc.</p>
		<p>Curabitur vitae eros auctor libero porta aliquet. Aenean ut lectus non eros malesuada cursus. Quisque eu nunc. Morbi erat. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec scelerisque. Nulla est. Integer et quam et lacus iaculis iaculis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia.</p>
		<a href="">read more...</a>
	</div>

	<div id="home_products">
		<h1>Lorem components and packages</h1>
		<div class="home_product">
			<img src="images/product_package.jpg" alt="Lorem Components - Gold Edition" title="Lorem Components - Gold Edition" width="194" height="194" />
			<p><a href="">Lorem Components <br /> Gold Edition</a></p>
			<a href=""><img src="images/details_button.jpg" alt="Details" title="Details" width="67" height="17" /></a>
		</div>
		<div class="home_product">
			<img src="images/product_package.jpg" alt="Lorem Components - Gold Edition" title="Lorem Components - Gold Edition" width="194" height="194" />
			<p><a href="">Lorem Components <br /> Gold Edition</a></p>
			<a href=""><img src="images/details_button.jpg" alt="Details" title="Details" width="67" height="17" /></a>
		</div>
		<div class="home_product">
			<img src="images/product_package.jpg" alt="Lorem Components - Gold Edition" title="Lorem Components - Gold Edition" width="194" height="194" />
			<p><a href="">Lorem Components <br /> Gold Edition</a></p>
			<a href=""><img src="images/details_button.jpg" alt="Details" title="Details" width="67" height="17" /></a>
		</div>
	</div>
</div>

There is only one more thing you will need to make your page look like it should: the CSS stylesheet. Create a folder called css on the same level with your index.php file. Inside this folder, create the file main.css and insert the following code inside:

*	{
	font-size: 1em;
	line-height: 1.2em;
	margin: 0px auto;
	padding: 0;
	text-align: justify;
	text-decoration: none;
	color: #333;
}

body	{
	background-color: #FFF;
	color: #000;
	font-family: Arial, Georgia, Helvetica, Verdana, sans-serif;
	text-align: center;
}

ul li {
	list-style: none;
}

img {
	border: 0;
}

h1 {
	padding: 0;
	font-weight: normal;
}

strong {
	padding: 0;
}

a {
	text-decoration: none;
}


#container	{
	color:  inherit;
	font-size: 0.8em;
	margin: 0 auto;
	text-align: left;
	width: 728px;
	text-align: center;
}

#logo {
	background: url('../images/logo.jpg') no-repeat #000 ;
	height: 55px;
	width: 100%;
}

#logo h1 {
	color: #FFC200;
	padding: 15px 0 0 60px;
	font-size: 180%;
}

#navigation {
	background: #000;
	height: 20px;
	border-top: 1px #F0F0F0 dotted;
}

#navigation ul {
	float: right;
	margin: 0;
}

#navigation ul li {
	float: left;
	color: #F0F0F0;
}

#navigation ul li a{
	color: #F0F0F0;
	padding: 0 10px;
}

#navigation ul li a:hover{
	color: #FFC200;
}

#banner {
	background: url('../images/banner_bg.jpg') repeat-x;
	height: 260px;
}

#banner img {
	padding-left: 10px;
	float: left;
}

.banner_text {
	width: 450px;
	float: right;
	padding-top: 30px;
}

.banner_text  h1{
	font-size: 200%;
}

.banner_text p{
	padding: 5px 20px 0 20px;
}

.banner_text ul{
	padding: 5px 0 0 40px;
}

.banner_text ul, .banner_text p{
	font-size: 110%;
}

#home {
	background: #F0F0F0;
}

#home h1 {
	font-size: 150%;
}

#home p {
	padding: 5px 0;
}

#home a {
	color: #B50000;
	text-decoration: underline;
	font-weight: bolder;
	font-size: 90%;
}

#home a:hover {
	color: #FFC200;
}

#home_welcome {
	padding: 20px 30px;
}

#home_products  {
	width: 100%;
	background: #F0F0F0;
	display: block;
	overflow: hidden;
	padding-bottom: 20px;
}

#home_products  h1{
	padding: 10px 30px;
}

#home_products  p{
	text-align: center;
}

.home_product {
	width: 33%;
	text-align: center;
	float: left;
}

#footer {
	background: #000;
	width: 100%;
	display: block;
	overflow: hidden;
	padding: 5px 0;
}

#footer p, #footer ul li, #footer ul li a {
	float: left;
	color: #F0F0F0;
	padding: 0 2px;
	font-size: 90%;
}

#footer p a {
	color: #F0F0F0;
}

#footer p {
	padding-left: 30px;
}

#footer ul {
	float: right;
	padding-right: 30px;
}

3.3 Stitching all together

Once you have all your page blocks it's time to use them. Excited?

Let's get back to the index.php file we have created and open it. Now it's time to use those include statements. Inside the div labeled "container" insert the following code:

	
	<?php include('pages/logo.php'); ?>
	<?php include('pages/navigation.php'); ?>
	<?php include('pages/banner.php'); ?>
	<?php include('pages/home.php'); ?>
	<?php include('pages/footer.php'); ?>

Noticed how we include the blocks in the same order as they appear in the page? This is not absolutely necessary because the blocks will be positioned by your CSS. It's simply a good coding practice and might save you from some headachesevery now and then when you'll have to debug a certain page.

As you can see, there is no magic in this but, still, let's have a closer look. First we are enclosing our code in PHP tags (<?php ?>), This is needed to tell the server it has to interpret the code inside these tags as PHP code and not just simply display it as regular text.

Next, we are using the include statement itself. The generic form of this statement is:

	
include('pages/the_name_of_file_to_be_included.php');

What happens with this code? When the server prepares the page for the browser, it will simply parse over the index.php file and include all the code inside the files that are included. This way, the resulting page will contain all the code you have inserted in your blocks. In other words, the body of the resulting page will look like this:

<body>
<div id="container">
	<!-- Create the logo stripe -->
	<div id="logo">
		<h1>Lorem Components</h1>
	</div>

	<!-- Create the top menu/navigation -->
	<div id="navigation">
		<ul>
			<li><a href="">Home</a></li>
			<li><a href="">About us</a></li>
			<li><a href="">Products</a></li>
			<li><a href="">Licensing</a></li>
			<li><a href="">Contact us</a></li>
		</ul>
	</div>

	<!-- Create the banner -->
	<div id="banner">
		<img src="images/banner_package.jpg" alt="Lorem Components - Gold Edition" title="Lorem Components - Gold Edition" width="260" height="260" />
		<div class="banner_text">
			<h1>Lorem Components - Gold Edition</h1>
			<p>Quisque tincidunt eros et lectus. Duis a velit id turpis dapibus consectetuer. In pellentesque erat nec eros. Donec nonummy, neque a facilisis adipiscing, urna libero facilisis ligula.</p>
			<ul>
				<li>- Duis a velit</li>
				<li>- Dapibus consectetur</li>
				<li>- Pellentesque erat</li>
				<li>- Donec nonummo</li>
				<li>- Quisque tincidunt</li>
				<li>- Libero facilis</li>
			</ul>
		</div>
	</div>

	<div id="home">
		<div id="home_welcome">
			<h1>Welcome to Lorem Designs</h1>
			<p>Quisque tincidunt eros et lectus. Duis a velit id turpis dapibus consectetuer. In pellentesque erat nec eros. Donec nonummy, neque a facilisis adipiscing, urna libero facilisis ligula, non consequat felis purus eu ante. Sed vitae turpis vitae quam varius rutrum. Phasellus vehicula. Nulla viverra. Sed sed nulla eu lectus consectetuer gravida. Praesent at metus. Maecenas eget justo at tortor auctor pretium. Integer sit amet nunc.</p>
			<p>Curabitur vitae eros auctor libero porta aliquet. Aenean ut lectus non eros malesuada cursus. Quisque eu nunc. Morbi erat. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec scelerisque. Nulla est. Integer et quam et lacus iaculis iaculis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia.</p>
			<a href="">read more...</a>
		</div>

		<div id="home_products">
			<h1>Lorem components and packages</h1>
			<div class="home_product">
				<img src="images/product_package.jpg" alt="Lorem Components - Gold Edition" title="Lorem Components - Gold Edition" width="194" height="194" />
				<p><a href="">Lorem Components <br /> Gold Edition</a></p>
				<a href=""><img src="images/details_button.jpg" alt="Details" title="Details" width="67" height="17" /></a>
			</div>
			<div class="home_product">
				<img src="images/product_package.jpg" alt="Lorem Components - Gold Edition" title="Lorem Components - Gold Edition" width="194" height="194" />
				<p><a href="">Lorem Components <br /> Gold Edition</a></p>
				<a href=""><img src="images/details_button.jpg" alt="Details" title="Details" width="67" height="17" /></a>
			</div>
			<div class="home_product">
				<img src="images/product_package.jpg" alt="Lorem Components - Gold Edition" title="Lorem Components - Gold Edition" width="194" height="194" />
				<p><a href="">Lorem Components <br /> Gold Edition</a></p>
				<a href=""><img src="images/details_button.jpg" alt="Details" title="Details" width="67" height="17" /></a>
			</div>
		</div>
	</div>

	<div id="footer">
		<p>Copyright © <?php echo date("Y"); ?> - <a href="">yoursite.com</a></p>
		
		<ul>
			<li><a href="">Home</a></li>
			<li>|</li>
			<li><a href="">About us</a></li>
			<li>|</li>
			<li><a href="">Products</a></li>
			<li>|</li>
			<li><a href="">Contact us</a></li>
			<li>|</li>
			<li><a href="">Terms of use</a></li>
			<li>|</li>
			<li><a href="">Privacy policy</a></li>
		</ul>
	</div>
</div>
</body>

Notice how the include statements got replaced by the actual code in your block files? That's all the basic magic!

Now, if you open the index.php file in your browser you should see the home page being displayed the way it was in the Photoshop mockup.

3.4 Adding code for the dynamic pages

Now that you we are through the basic steps, it's time to care about the dynamic content area.

First, I would like to mention a bad coding practice that I see quite often on the forums. Theoretically, you could use your blocks to build all your pages separately. that would mean having an index.php file, an about-us.php file and so on, all including the same blocks (logo.php, navigation.php, etc). While this might make sense at a first glance will proove hard to maintain of you decide to add/remove some blocks. In this case, you would have to go through all the file and add/remove the corresponding blocks. This might be an easy task for small sites but if you are building larger ones it will become tedious work in no time.

The alternative to the above is to use a single "framework" page where you would only replace the dynamic parts as needed. Look at this as if it would be a picture frame. When you want to replace the picture you are not throwing away the whole frame, aren't you?

One popular method to implement the mechanism above is to rely on query strings in the URL. This means you will specify the page to be displayed using an extra string of characters in the page's URL, like http://www.yoursite.com/index.php?page=1. Notice the "page=" part in the URL? This is the part that will specify which page to display. You might also consider this as calling a function inside the index.php page with the parameter "page" set to the value "1".

Now that we settled on the method to use let's implement it. As you can easily tell from the URL content, the main code will be implemented inside the index.php file. First, we need some code to extract the page parameter from the URL. This is done with the following code, placed in the page header (that is, before the closing </head> tag):

<?php
	//Extract page ID
	$page = (isset($_GET['page'])) ? intval($_GET['page']) : '1' ;
?>

This one line of code will analyze the URL and extract the "page" parameter assigning it to the PHP variable $page. There is no direct relation between the name of these two parameters so yuo can really use almost anything. In case there is no page parameter in the URL, the $page variable will get the value "1". Easy enough, don't you think?

Great! Now that we have extracted the parameter from the URL and assigned it's value to an internal PHP variable, we'll have to define an equivalence between the different pages and the value of the "page" parameter in the URL.

In our example, we have the following pages:

We will assign each of these pages with a unique page ID that we'll be using in the page URL. The assignement list might look like this:

Now that we have a unique ID for each page, we can build the corresponding URL for each page:

Notice how we simply added the page ID to the end of the URL? That's the place where it all happens.

Let's stop for a moment and summarize what we have done so far in this sub-chapter:

Before proceeding, let's create the remaining files for the dynamic pages. We already have home.php for the home page content. The other pages will be similar to this one:

about.php

<h1>About us</h1>
<p>Insert a few lines about yourself and your company here.</p>

products.php

<h1>Our products</h1>
<p>Insert a few lines about your product here.</p>

licensing.php

<h1>Licensing</h1>
<p>Insert a few lines about the product licensing here.</p>

contact.php

<h1>Contact us</h1>
<p>Insert your name, address, phone number and a contact form here.</p>

terms.php

<h1>Terms of use</h1>
<p>Insert your website's term of use here.</p>

privacy.php

<h1>Privacy</h1>
<p>Insert your website's privacy policy here.</p>

To keep the whole thing tidy, let's move all the php files except of index.php, to a folder called "pages".

Once we have all this informaton, we can start implementing the dynamic part of our pages. For this let's get back to the index.php file. You remember the list of include statements we made?

	<?php include('pages/logo.php'); ?>
	<?php include('pages/navigation.php'); ?>
	<?php include('pages/banner.php'); ?>
	<?php include('pages/home.php'); ?>
	<?php include('pages/footer.php'); ?>

We'll be extending this now by adding some code that will load the different content pages depending on the selected page. We will be using the page ID to select between the pages. Replace this line

	<?php include('pages/home.php'); ?>

with this code:

	<?php 
		switch ($page) {
			case '1':
				include('pages/home.php');
				break;
		
			case '2':
				include('pages/about.php');
				break;
		
			case '3':
				include('pages/products.php');
				break;
		
			case '4':
				include('pages/licensing.php');
				break;
		
			case '5':
				include('pages/contact.php');
				break;
		
			case '6':
				include('pages/terms.php');
				break;
		
			case '7':
				include('pages/privacy.php');
				break;
			
			default:
				include('pages/home.php');
				break;
		}
	?>
	

This construct will check the value of the PHP variable $page and include the corresponding page. You notice how the page IDs we have defined in a previous step are used in the case statements? Also, notice how for each of these ID we include the corresponding page block?

There is also a special part of the code above:

	default:
		include('pages/home.php');
		break;

This tells the server to include home.php whenever the URL contains a page ID that is not assigned to any page (ex: index.php?page=12345).

3.5 Building the links

Remember that we left the links all empty? It's time to take care of this part as well. I'll do it with the top navigation and leave it to you to do it for the other links.

Let's open the block file for the navigation, navigation.php:

<div id="navigation">
	<ul>
		<li><a href="">Home</a></li>
		<li><a href="">About us</a></li>
		<li><a href="">Products</a></li>
		<li><a href="">Licensing</a></li>
		<li><a href="">Contact us</a></li>
	</ul>
</div>

Now, let's add the links we have defined in the previous chapter:

<div id="navigation">
	<ul>
		<li><a href="index.php?page=1">Home</a></li>
		<li><a href="index.php?page=2">About us</a></li>
		<li><a href="index.php?page=3">Products</a></li>
		<li><a href="index.php?page=4">Licensing</a></li>
		<li><a href="index.php?page=5">Contact us</a></li>
	</ul>
</div>

Repeat this for all the links in your website.

This concludes the tutorial. I hope you enjoyed reading this just as much as enjoyed writing it.