How to Build a CMS

A CMS or Content Management System is a type of web site that allows the user to edit content without having to know HTML. Standard blogging software like WordPress is basically a CMS that displays the content in reverse chronological order. On that note here is a very cool technique using PHP, HTML, JavaScript and a very cool, free, text editor called TinyMCE. This technique will show you how to build a CMS or content management system for a website that stores the content in text files.There are definitely better ways to do this but I am keeping it as simple as possible to show the technique in its most basic form.

Now days we use a database because they are much more secure and much more manageable. However this technique, using text files in a password protected folder as our database, makes a website, and an online admin area the user can browse to, enter a password and gain access to an “editable” version of each page. In other words its kind of like WordPress’ great, great granddaughter in that after entering in a password you browse to the page and a text editor is there and your text file has been loaded in, ready for editing. Edit, hit save and your page is updated. Pretty cool.

All we’re… I mean, all you’re going to make is 2 HTML files, 2 PHP files, a stylesheet, a few text files and TinyMCE, a free Word-like text editor that you can upload to your site and target with simple scripting. Get TinyMCE here. There are others but Tiny’s been around a while and it’s what I’m using here.

You could also do this with a lot less files but I am keeping with the policy of separating layout, processing and content… it’s the right thing to do. Keep in mind this only works on a server with PHP. If you have a WordPress blog you have a server, and you can create a directory there using Filezilla or something similar if you want to try this out.

Your main directory for this project will have 4 or 5 sub directories. This example uses no images so there are only 4 sub directories here. They will be “css”, “pages”, “secure”, and “tinymce”. The tinymce folder will have… the TinyMCE files. The first two files you need are the HTML files. The header and the footer of the web pages. These appear on every page and contain the menu and the site title or a logo if you want. The header file contains the usual HTML header stuff. This particular example does not have the option of individual titles, descriptions, and keywords for each page. It is totally possible but I will save that for another discussion. If your just starting out need an intro to basic HTML please check out How To Make A Website For Beginners and The Son of How To Make A Website.

To begin, these two files go in the project Root Directory.

The Header: save as header.html

<!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>
  <title>My Dynamic Web Site</title>
  <link rel=stylesheet href="/css/style.css" type="text/css" />
</head>
<body>

<div id="wrapper">
  <div id="pagetop"><h1>My Site</h1></div>

    <div id="leftcol">
      <div id="colorblockleft">&nbsp;</div>
      <div id="menu">
      <ul>
        <li><a href="index.php?page=page1">News</a></li>
        <li><a href="index.php?page=page2" class="n1">About</a></li>
        <li><a href="index.php?page=page3">Photos</a></li>
        <li><a href="index.php?page=page4" class="n1">Contact</a></li>
        <li><a href="index.php?page=home">Home</a></li>
      </ul>
    </div>
  </div>

  <div id="rightcol">
    <div id="colorblockright">&nbsp;</div>
    <div id="pagecontent">

The Footer: save as footer.html

    </div>
  </div>

  <br clear="all" />
  <div id="footer">
    <a href="index.php?page=page1">News</a> &nbsp; &bull; &nbsp;
    <a href="index.php?page=page2>About</a> &nbsp; &bull; &nbsp;
    <a href="index.php?page=page3">Photos</a> &nbsp; &bull; &nbsp;
    <a href="index.php?page=page4">Contact</a> &nbsp; &bull; &nbsp;
    <a href="index.php?page=home">Home</a><br />
    <a href="http://www.sheppco.com" target="_blank" >Powered by Sheppco</a>
  </div>

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

Now the processing. The next file you’ll make is a .php file. This file does several things all of which cumulate into a brand new HTML page created dynamically, or “on the fly”. First it calls in the header file you just made. Next it defines the home page, rather, the default .txt file that will be displayed if no other pages are selected. Next it checks the specified directory (“pages”) to see if the requested file is there. If not then an error statement is written. If the file is there, write it to the page. It then finishes off the dynamically generated page by calling in the footer, footer.html.

The Page Body: Save as index.php

<?php
  include("header.html");

  // ets $page to "home.txt" if a parameter isn't passed
  if ($_GET['page']) {
    $page = $_GET['page'] . '.txt';
    } else {
    $page = 'home.txt';
  }

  // Check to see if file exists and include it in.
  if (file_exists("pages/$page")) {
    include("pages/$page");
    // If page doesn't exist, give an error message.
    } else {
    echo("<h1 align=\"center\">Page cannot be found</h1>\n");
  }

  include("footer.html");
?>

The content: Take the below snippet and use it to make 5 files that will go into the “pages” directory. Name one home.txt. Name the next four pages page1.txt, page2.txt, page3.txt, and page4.txt.

<h1>Page Title</h1>
<p>This is the page content. It will be rendered as HTML so you can use
any HTML element you want such as <strong>Bold</strong> and <em>Italic</em>,
lists and forms and links like this <a href="http://normansheppard.com">The Web Design Guide</a>.</p>

The Stylesheet: To finish off the web site we need some style save the below code your “css” directory as style.css

body {
  background-color:#9cafc3;
  font: normal 11px Verdana, Arial, sans-serif;
  color: #333333;
  line-height:18px;
}
a:link, a:visited {
  color:#0092cf;
  text-decoration:none;
}
a:hover {
  color:#ff6928;
  text-decoration:underline;
}
h1 {
  font: normal 18px Arial;
  margin: 0px;
}
h2 {
  font: bold 22px Arial;
  display:inline;
  margin:5px;
}

#wrapper {
  position:relative;
  top:0px; left:0px;
  padding:0px;
  margin:0px auto;
  width:780px;
  border-top:1px solid #000;
  border-left:1px solid #000;
  border-right:1px solid #000;
  background-color:#fff;
}
#pagetop {
  padding:10px 0px 0px 10px;
  height:80px;
  margin:0px;
  font:bold 36px fantasy;
}
#colorblockleft {
  background-color:#ff6928;
  height:20px;
}
#colorblockright {
  background-color:#003869;
  height:20px;
}

#leftcol {
  float:left;
  width:220px;
  height:300px;
  padding-bottom:50px;
  background-color:#eeeee6;
}
#menu, #menu ul {
  display:block;
  width:220px;
  list-style-type:none;
  margin:0px;
  padding:0px;
  height:46px;
}
#menu li a {
  display:block;
  height:28px;
  color:#666;
  border-bottom:1px solid #fff;
  padding:15px 0px 0px 10px; font-weight:bold;
  text-transform:uppercase;
}
#menu li a.n1 {
  background-color:#eceae5;
}
#menu li a:hover {
  background-color:#fff;
  color:#ff6928;
}

#rightcol {
  float:left;
  width:560px;
}
#pagecontent {
  padding:5px 15px 15px 15px;
}

#footer {
  clear:both;
  position:relative;
  top:0px;
  left:0px;
  padding:0px;
  margin:0px auto;
  width:780px;
  text-align:center;
  font-size:10px;
  color:#666;
  background-color:#efefef;
  padding:10px 0px;
  border-bottom:1px solid #000;
  border-top:1px dashed #666;
}

There’s the website. Now we create the admin area that allows the user to edit the site content. Keep in mind that this is a very simple implementation for the purpose of demonstrating particular programming ideas. Security will be in the form of a password protected folder via your .htaccess file. I am not discussing the .htaccess file here so If you don’t know what .htaccess is or how to edit one specific to a particular folder, I recommend deleting the “secure” folder after your done experimenting. Some hacker may find it and post ice cream recipes all over your pages.

The Admin: save in “secure” directory as index.php

<?php
  include("../header.html");

  // Get the page name from the query string
  $page = $_GET['page'] . '.txt';

  if (!$_GET['page']) {
    echo("<h1>Select a page from the main menu to begin.</h1>\n");
    include("../footer.html");
    exit;
  }

  if ($_POST['page']) {
    $handle = fopen("../pages/$page", "w");
    fwrite($handle, $_POST['page']);
    fclose($handle);
    echo($_POST['page']); // OR include("../pages/$page");
    include("../footer.html");
    exit;
  }

  if (file_exists("../pages/$page")) {
    $FILE = fopen("../pages/$page", "rt");
    while (!feof($FILE)) {
    $text .= fgets($FILE);
  }
  fclose($FILE);
  } else {
    echo("<h1>New Page: $page</h1>\n");
    $text = "<p></p>";
  }

  echo <<< EOM
  <script language="javascript" type="text/javascript"
    src="/tinymce/jscripts/tiny_mce/tiny_mce.js"></script>
  <script language="javascript" type="text/javascript">
    tinyMCE.init({
    mode : "textareas",
    theme : "advanced",
    theme_advanced_toolbar_location : "top",
    theme_advanced_toolbar_align : "center",
    theme_advanced_path_location : "bottom"
    });
  </script>
  EOM;

  $this_page = $_SERVER['PHP_SELF'];
  $query_string = $_SERVER['QUERY_STRING'];
  echo("<form method=\"post\" action=\"$this_page?$query_string\">\n");
  echo("<textarea id=\"page\" name=\"page\" rows=20 cols=60>\n");
  echo(htmlspecialchars($text));
  echo("</textarea>\n");
  echo("<input type=\"submit\" value=\"Save\">\n");
  echo("</form>\n");

  include("../footer.html");
?>

That’s it. This file is similar to the root directory version in that it reads in the header, checks for files, prints an error or the selected page then finishes off by reading in the footer. Do you see the raw potential of this simple idea? Every time I read through it I think ‘oh yeah, you could do this and this here too’ but… It’s already been done, and quite well, and you can get it for free at WordPress.org.

Not a lot of explanation here either but as I’ve said before, its much easier for me to understand things when I have a working example in front of me.

Hope this finds someone who finds it useful.

15 Replies to “How to Build a CMS”

  1. I can’t seem to get this to work, when I go to the secure directory it shows a blank page and has an internal server error. Any ideas? I would really be interested to see the potential of this.

  2. Hey Matt,

    PHP has a thing for “white space” so be sure all the code is NOT indented or tabbed over. I usually tab code for easier reading however this can create white space which will break the script.

  3. Hi, thanks for your post. That is the same method I have used for developing my own CMS. I wonder if that is the BEST method I can use. My worries are essentially releated to SEO problems, how google and friends react to this kind of architecture (are they able to reach and index the txt, or database, content?).
    Sorry for my english, probably I have made a lot of errors 😉
    Cheers,
    Davide

  4. This is definitely not the only method and as it is, this is not SEO friendly. However, with a little research into the apache mod_rewrite module it is possible to re-write your URLs so that they are more SEO friendly.

    As for the fact that the content is served from a text file or even if it was from a database, search engines do in fact like this type of architecture, I have read that they actually prefer it.

    Thanks for the comment!

  5. I have this error “Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE, expecting T_STRING or T_VARIABLE or T_NUM_STRING in /home/interface/domains/intercms.co.cc/public_html/cms/secure/index.php on line 47” and I dont know what to do.. Can you help me?

  6. If you are cut and pasting from this page then you have to be careful about blank spaces and special characters. You could try pasting into a plain text editor first. I KNOW you’re not using Word… right?

  7. Thanks for your post. I also had the parse error but i repaired it and i dont know how.

    Ted

  8. I was testing this script also. For those that encounter the white space problem. Remove any white space before the EOM; line. This did it for me.

    Dave

  9. Iagree with the above poster. I think which this exceptional how the facts is laid out in an a quite concise, and helpful fashion. Thanks for the wonderful info! Properly Said!

  10. This is absolutely the exact thing I needed. Thanks for introducing me to tinyMCE!! you are awesome! i’m all excited now, this kicks ass.

  11. Hi Norman,

    I like this tutorial. I’m having problems echo <<< EOM …. EOM;

    I follow all your instruction and you're right … this a unique idea!

    The website works but on the "The Admin" I have problems. I save the file but when I type it in my browser and open it I can't see the TinyMce. But when I used the prototype (the example of tinymce) and open it works but I can't seen to open the editor in Admin section?

    any suggestion?

    Will you or if you have time, I know you have a lot experience in web development can you post a article on MYSQLI or PDO? Right now, not just me but a few of friends are having issues or having confusing to learn it!

    but anyway I'm having problems with the Admin section. Any Suggestions? Thanks?

  12. Keep in mind that this article was written in 2008! PHP is now on version 5 so there may be some conflicts. I would suggest following the code, finding where the error is happening and then looking to other more comprehensive tutorials on PHP.

    Good luck.

Comments are closed.