Grow your CSS skills. Land your dream job.

PHP for Beginners: Building Your First Simple CMS

Published by Guest Author

The Magic of PHP + MySQL

It's safe to say that nearly every website that's up-to-date these days is using some form of content management system (CMS). While there are a ton of great free options that provide us with a CMS to power a website (WordPress, Drupal, etc.), it doesn't hurt to peek under the hood and get a feel for how these systems work.

To get our feet wet as back-end developers, we'll be creating a simple PHP class that will:

  • Create a database
  • Connect to a database
  • Display a form with two fields
  • Save the form data in the database
  • Display the saved data from the database

Download Files

This class is intended to give you a feel for how PHP and MySQL interact together, and to show the basics of a CMS. I'll be skipping explanations of some of the very basic programming stuff, so if at any point you feel lost, checkout the course Diving into PHP and give yourself a crash-course in PHP. I'll try not to lose anyone, though, I promise.

Building the Class

Our first step is to simply lay out the class in a file named 'simpleCMS.php' so we have a road map to work with.

<?php

class simpleCMS {
  var $host;
  var $username;
  var $password;
  var $table;

  public function display_public() {
    
  }

  public function display_admin() {
    
  }

  public function write() {
    
  }

  public function connect() {
    
  }

  private function buildDB() {
    
  }
}

?>

As you can see, we're creating one class with four variables and five methods. I've opted to use PHP's object-oriented approach because it makes for cleaner code in large projects, and, in my opinion, it's just good practice.

The Variables

In this case, all four variables are for connecting to the database: $host, $username, $password, and $table provide a path and access to our database on the server. For now, we'll leave those empty and move on to our database, which is constructed by the method buildDB().

Build the Database

private function buildDB() {
    $sql = <<<MySQL_QUERY
        CREATE TABLE IF NOT EXISTS testDB (
            title	VARCHAR(150),
            bodytext	TEXT,
            created	VARCHAR(100)
    )
    MySQL_QUERY;

    return mysql_query($sql);
}

This function runs a MySQL command that checks the database to see if testDB exists. If so, it simply passes along a notification of success; if not, it creates our table and assigns three columns to hold data.

Connect to the Database

Now that we have a function to build our table, let's create the function that will connect to our database.

public function connect() {
    mysql_connect($this->host,$this->username,$this->password) or die("Could not connect. " . mysql_error());
    mysql_select_db($this->table) or die("Could not select database. " . mysql_error());

    return $this->buildDB();
}

We call mysql_connect() to hook into our database, and then mysql_select_db() to make sure we save our data in the right place. Both of these functions are accompanied by the die() command, which essentially says, "in the event that this function fails, stop execution of this script and display a message."

Our connect() function connects to the database and gets us pointed in the right direction, then runs our buildDB() function. Remember the grammatically awkward "IF NOT EXISTS" part of our MySQL command? Because we're going to run this function every time the page is loaded, we have to make sure we're not overwriting our database with every function call, and that's exactly what that phrase requires.

Build the Form

So, we've got a database. Now we just need to put stuff in it!

public function display_admin() {
    return <<<ADMIN_FORM

    <form action="{$_SERVER['PHP_SELF']}" method="post">
      <label for="title">Title:</label>
      <input name="title" id="title" type="text" maxlength="150" />
      <label for="bodytext">Body Text:</label>
      <textarea name="bodytext" id="bodytext"></textarea>
      <input type="submit" value="Create This Entry!" />
    </form>

ADMIN_FORM;
}

Again, this is a very simple function. When called, it simply returns the HTML markup to create our form. You'll notice, however, in the action attribute of the form element, that I've used the variable $_SERVER['PHP_SELF']. This is, essentially, a shortcut that references the file you're currently using (in our case, it's display.php). This is useful if you'll be reusing your code across a site and don't necessarily want to rewrite this function for each page.

I'm also going to take a second right now to talk about the method I'm using to return the HTML. It's a format used in PHP called HEREDOC syntax, and I love it.

The primary advantage of HEREDOC is that it allows you to include formatting in your output. This is extraordinarily useful for folks like me who take issue with cluttered source code. You can read more about HEREDOC syntax and its ilk in the PHP manual.

Saving the Data to the Database

Our form will allow us to input information, so how do we save it? That's where our write() method comes in.

public function write($p) {
    if ( $p['title'] )
      $title = mysql_real_escape_string($p['title']);
    if ( $p['bodytext'])
      $bodytext = mysql_real_escape_string($p['bodytext']);
    if ( $title && $bodytext ) {
      $created = time();
      $sql = "INSERT INTO testDB VALUES('$title','$bodytext','$created')";
      return mysql_query($sql);
    } else {
      return false;
    }
}

Let's start with the function call itself — we're passing a variable to this one, which we haven't done so far. Our variable $p is going to hold the information sent from our form via the post method.

Once inside the function, we start with a conditional statement that's checking to see if the the title value was set in the form before it was submitted, and if so, we're setting our $title variable to the $_POST['title'] value (NOTE: we're using the function mysql_real_escape_string() as a precaution against potentially dangerous input, which is important to keep in mind when you're building anything that will allow users to input information). If $_POST['title'] wasn't set, we skip this line, leaving the $title variable unset.

This process is repeated for our second input, and then both variables are checked to make sure nothing is blank before saving to the database. If both variables are set, we then set the $created variable with the current Unix timestamp, which we'll use to sort our entries chronologically when we view them in the future.

We now have three variables, and because we've run checks, we know that all three variables are not empty. Now we can write our MySQL query that will save the entry in the database!

Displaying the Information from the Database

Now that we have the means to put information into our database, we need to create a way to get that information back out. This is where display_public() comes in. This is by far the most complex of our methods, so let's really take our time and figure out what's going on inside.

public function display_public() {
    $q = "SELECT * FROM testDB ORDER BY created DESC LIMIT 3";
    $r = mysql_query($q);

    if ( $r !== false && mysql_num_rows($r) > 0 ) {
      while ( $a = mysql_fetch_assoc($r) ) {
        $title = stripslashes($a['title']);
        $bodytext = stripslashes($a['bodytext']);

        $entry_display .= <<<ENTRY_DISPLAY

    <h2>$title</h2>
    <p>
      $bodytext
    </p>

ENTRY_DISPLAY;
      }
    } else {
      $entry_display = <<<ENTRY_DISPLAY

    <h2>This Page Is Under Construction</h2>
    <p>
      No entries have been made on this page. 
      Please check back soon, or click the
      link below to add an entry!
    </p>

ENTRY_DISPLAY;
    }
    $entry_display .= <<<ADMIN_OPTION

    <p class="admin_link">
      <a href="{$_SERVER['PHP_SELF']}?admin=1">Add a New Entry</a>
    </p>

ADMIN_OPTION;

    return $entry_display;
  }

The first thing to note when reading from a database is the way PHP and MySQL interact with each other. First, we ask the database a question (query), to which it replies with a result (resource). However, this result isn't really useful until we've decoded it using one of several methods that "fetch," or organize, the information that's contained inside into a usable form (array).

Our very first action in the above function is to set up our query in the variable $q. The asterisk (*) operator in MySQL means "everything," so our query is asking the database to select everything from entries in the table testDB in reverse chronological order, limited to the first three entries returned.

Now that the query is defined, we send it to the database using the function mysql_query(). The resulting resource is stored in the variable $r. This is where it gets a bit tricky.

We now run a conditional statement that says, "IF mysql_query() didn't fail, AND IF the number of entries returned was greater than zero, process the result, OR ELSE display a default message."

If $r contains entries from the database, we now have to "fetch" that data. Information from the database is returned as an array, which is organized similarly to the database table itself. The function mysql_fetch_assoc() will take the resource and break each entry into an associative array (this means that when we save the result of mysql_fetch_assoc() into the variable $a, the data from the entry will be accessible by the column names in the database, i.e. $a['title']).

However, mysql_fetch_assoc() only gives us one entry at a time. To get all of the returned entries, we have to use a while loop. Essentially, we're saying, "WHILE $r has values we haven't used yet, get the next entry in line and do the following actions with it."

In this case, we're going to check the entry to make sure that data was returned, then remove the slashes that were added when we saved the information to the database using stripslashes(). After that, we simply wrap the variables in some HTML and, voila! we've got screen-ready content!

As a final step, the code adds a link to the bottom that allows users to add an entry. It's worth noting the use of the ".=" operator used in the while loop and when creating the "Add a New Entry" link; a function can only return one variable, so we need to append the new information to the existing variable. If we just used the equals sign ("="), we would overwrite existing data and end up with just a link to the form and no content.

So, you've now written your first CMS class! You can easily write and retrieve data to and from a database. All that's left to do is to try it out!

Using the Class

To use our class, we need to create a separate file. I'm going to call it "display.php", which I'll save in the main web folder, with our class saved as "simpleCMS.php" in a folder called "_class" within the main folder. To start, we just set up a document with plain ol' HTML.

<!DOCTYPE html>
<html lang="en">

  <head>
    <title>SimpleCMS</title>
  </head>

  <body>

  </body>

</html>

To use our class, we just have to insert a little PHP between the body tags:

<?php

  include_once('_class/simpleCMS.php');
  $obj = new simpleCMS();
  $obj->host = 'database.host.net';
  $obj->username = 'DB1234567';
  $obj->password = 'DBpassword';
  $obj->table = 'DB1234567';
  $obj->connect();

  if ( $_POST )
    $obj->write($_POST);

  echo ( $_GET['admin'] == 1 ) ? $obj->display_admin() : $obj->display_public();

?>

First and foremost, we have to include the class using the include_once() function. Then, we have to instantiate our object so that our code knows what's going on. Third, we set all of those variables we talked about toward the beginning of this tutorial. You'll have to replace all of those values with the information you get from your own server or hosting company. And fourth, we connect to our database using the connect() method.

After we've connected to the database, we check to see if any $_POST information exists. This is because we're using the same file for input, processing, and display of information. If anything was passed via $_POST, we run the write() function to validate it and save it to the database. Then, we use some shorthand trickery to run a conditional statement. In essence, we're saying, "IF $_GET['admin'] is set to 1, then show the form using display_admin(), OR ELSE show me the stored entries using display_public()."

And that's it! Once you get a feel for it, this sort of basic programming will allow you to start exercising total control over websites you build, whether you decide to really dig in and build your own CMS framework or just improve an existing CMS by, say, writing a WordPress plugin.

Really, when it comes to modern web design, you should have at least some understanding of how things are working behind the curtain—understanding how a site works will better enable you to design sites that have a more fluid integration of form and function. And besides, adding PHP and MySQL to your curriculum vitae definitely won't hurt your credibility...

Download Files

Jason Lengstorf runs Ennui Design, a freelance design and development effort. He has a fetish for building custom applications from scratch, including his own content management system. When he's not glued to his keyboard, he's likely to be wearing cowboy shirts, deadlifting, or pretending to know stuff about wine.

Important Note

This code is written for demonstration purposes only. Several security holes have been pointed out in the comments, which I have addressed in Part Two of this tutorial series Editor's note: There is no part two of this series anymore. Jason recommends his book PHP for Absolute Beginners as a resource for best practices. Still, I would strongly advise not using it for production websites without further testing.

I have covered some of the bases with security, but other issues may exist. Further reading on security risks and safe PHP code can be found here. Please read through this before implementing this code on your server to avoid potential security holes.

Comments

  1. Permalink to comment#

    This is excelent! Exactly what I personally need to kick off with some proper PHP Scripting! Thanks again for the quality :)

  2. Rafael de Almeida
    Permalink to comment#

    Great article, Chris!

    But just a fix…the HEREDOCS starts with <<< instead of >>>

  3. Permalink to comment#

    Thank you! This is exactly what I needed for so long!

  4. Permalink to comment#

    AWSOME tutorial! I’m really loving the quality of stuff that you’ve been writing on CSS-Tricks recently, it’s superb. Definitely going to follow along with this one and use it as a basic CMS for clients who want brochure sites.

    A great follow up to this (from my point of view) would be how to adapt this simple CMS in the same format to support multiple pages.

  5. Permalink to comment#

    In the process of updating my clients website to make it easier for them to update in office. This will work perfectly! Thanks a bunch!

  6. Permalink to comment#

    Use sql parameters for the sake of security…

  7. Permalink to comment#

    Oh, awesome, I just started learning PHP, and have been looking for something like this! Thanks!

  8. Permalink to comment#

    Great tutorial! This is a great example of simplicity but yet has advanced concepts behind it. In the future could you maybe expand this to include updating, and deleting?

    -Brenelz

  9. Permalink to comment#

    I haven’t actually found the time to read this properly yet… but from skimming it looks like a great article. This is exactly what is needed out there… simple, step by step instructions to PHP and CMS development. Great work Chris. Thanks for your efforts.

  10. Great tutorial!

    There are a few things that I feel should be pointed out/considered when using OOPHP.

    Classes only make your code better when used correctly. This class isn’t that much more useful than if it were done in procedural code. Basically it’s too broad. Normally you’d break all that functionality into multiple classes and utilize them in a CMS class.

    class DB_MYSQL (functions for CRUD actions against a mysql db)

    class DBConnect (functions for connecting to a database – should be a singleton pattern)

    class Template (functions for displaying the form)

    class ValidateData (functions for filtering/validating user input)

    Thanks for the great write up!

  11. Great tutorial, looking forward to more tutorials on the development of cms’s and php!

  12. Permalink to comment#

    Precioso!!

  13. Martin
    Permalink to comment#

    Just when I wanted to start to learn some PHP.Good way to begin.
    Thanks for this one, keep on coming with this kind of tutorials.

  14. hatseflats
    Permalink to comment#

    Fur fuck sake, use a framework! I agree that any PHP developer should be able to do this in 5/10 minutes, but come on, why waste time like this? This is why PHP applications grow to be unmaintainable monstrocities of vague undocumented code…

    • I know, JEEZ, why would you want to LEARN something when it’s already done. That’s why I’d never learn to play and instrument, there are already loads of albums already there for me to listen to.

    • Great tutorials are to help people “learn”… experienced developers also had to start somewhere.

    • Permalink to comment#

      Hahaha, great answer Chris… @Hafseflats is true that WordPress, Joomla help the Content Management, but also sometimes a client needs an specific site and WordPress – Joomla, etc. doesn’t help us at all. This is the best way to improve our work and also is very professional.

    • You’re right, a framework. That’s a really great idea. I mean, it’s only about 1MB for a PHP framework, and this page being so short, is like only 4kb. Why on Earth would you want to save on BW and HDD space? Crazy.

      Also, why would you ever want to learn WHY stuff works. Because you know, the people who write CMS tools and frameworks were just born with CMS tools and frameworks already made.

      Thanks Jason Lengstorf, this tutorial was great because it only did the bare minimum and I have read through a few books and they always do tutorials on how to make a CMS, but they are always way drawn out and confusing for a beginner. Personally I use WP and SilverStripe, but this was an excellent example on how to interact with DBs.

  15. alrayyes
    Permalink to comment#

    I concur with hatseflats

  16. Permalink to comment#

    @hatseflats – why so negative? there are lots of disadvantages to using a framework, they aren’t perfect by any means – also, you don’t LEARN anything from frameworks, and I’m 99% sure that people visit css tricks to learn new skills.

    • Agreed.

      I also agree, however, that it’s probably not a terrible idea to use the existing frameworks out there. A real-world CMS is incredibly complicated, and, like hatesflats said, they can become sprawling nightmares for maintenance.

      Having a grip on PHP and MySQL and the way a CMS works, however, will give you a great advantage when working with a platform like WordPress, or if you need to create a small site or widget that would benefit from a database.

      To everyone else, thanks so much for all the positive feedback! And, of course, a HUGE thanks to Chris for running this tutorial. I’ll be taking some of the suggestions from the comments and writing tutorials to follow, so if you don’t mind, check my site or follow me on Twitter (@jasonatennui) to see those tuts in the future.

      Thanks again!

    • Permalink to comment#

      Following now! Thanks again for the great tutorial, and keep em coming!

    • I don’t like frameworks. They’re bloated and they try to do everything for you. I’ll write my own, much lighter, code, thank you. :)

  17. The problem with using a framework or CMS before trying to build your own is that you never learn what to look for in a good framework. Trying to get a handle on the hundreds of PHP packages is a huge task and you can narrow down your choice considerably by getting your hands dirty with your own code.

  18. i really want to thank you! today i´ve used my new knowledge directly with our new intranet! greetings

  19. Permalink to comment#

    I really like this, can wait to read more, maybe edit and put in some ajax, like small tut which includes everything.

  20. Is the download code updated with the error corrected that was referenced by a previous comment?

  21. Nice tut. Lets get some user authentication in part 2. :)

  22. Permalink to comment#

    Good tutorial.Thanks..

  23. Steven Gardner
    Permalink to comment#

    thanks for the great tut. will have a proper go through later. how can i edit the posts i create using this method?

  24. really nice tut. i’d love to see some more parts: user authentication, expanding what is posted, and maybe a skin for the admin screen. im excited. :)

  25. Paul
    Permalink to comment#

    This is very basic OOP, can you make more tutorials like this but expand more on it?

  26. Gavin Steele
    Permalink to comment#

    DO NOT CLICK ON THE DEMO BUTON

    Err you need to fix the demo link…. I get a message box informing me: Ooops! … CSS-tricks.com

    Might need to look at that?!?

    • This is fixed. Some asshole was doing a bunch of JavaScript injection.

      They were from http://www.totse.com/en/_feedback/feedback.html – in case anyone feels like stopping over there to tell them how super cool they are.

    • Permalink to comment#

      Not trying to beat a dead horse here, but isn’t this a good example of a reason to use a framework? The advantage here is that some very, very smart people (smarter than you or I) have thought about the hundreds of ways someone can hack your site. By using a framework, you can take advantage of those great minds.

      I know this is a very simple example, but you were hacked in a few minutes. The CMS example is very nice and well written and a great intro to PHP, but if one is to continue on this path they will soon have to deal with session management, sql injection, XSF, session fixation, and on and on. Wouldn’t it be nice to let a framework deal with that and you deal with adding functionality and good design?

      Let’s face it, WordPress, Drupal, and other blogs are frameworks. No one is complaining about their bloat.

      So all you code studs: instead of just injecting some off-hand comment on how you don’t like framework bloat, or that you will never learn to program by using a framework, give people some accurate information and let them learn.

      That being said, if you liked this tutorial, you should check out cakePHP tutorial on how to create a blog and see how it compares to the direct coding method.

    • Freek Lijten
      Permalink to comment#

      or you could write safe code……

      This is an example people, set up to have inexperienced programmers learn something. I doubt any of our first applications were , for instance, SQL-injection safe, but one day we learned of it and made sure it wouldn’t happen to us. If everything you needed to know to write a good and secure framework was here it wouldn’t be a tutorial but a book, a library even

  27. Gavin Steele
    Permalink to comment#

    Oh and I tried to click the OK button..its a no go.?!? very frustrating

  28. awesome tutorial, thanks ;)

  29. Permalink to comment#

    I think you should do something about Javascript Injection.

  30. Permalink to comment#

    Yep, great stuff! :D

  31. Permalink to comment#

    Tutorials like this are really enhancing my learning experience. Thank you to all that contribute.

  32. Permalink to comment#

    Thanks Chris. This is exactly what I was looking for to build my own CMS. I had one with text file instead of mySQL before, it didn’t work exactly as what I wanted.

  33. Permalink to comment#

    Thanks Jason and Chris for this great tutorial. :)

  34. Paul
    Permalink to comment#
    public function write($p) {
        if ( $p['title'] )
          $title = htmlentities(mysql_real_escape_string($p['title']));
        if ( $p['bodytext'])
          $bodytext = htmlentities(mysql_real_escape_string($p['bodytext']));

    That should fix all the XSS :D

  35. What would really be useful would be showing a way to make categories.. with posts that display on their own page.

  36. Permalink to comment#

    Thanks Chris and Jason for this tut. great job.
    P.S. I loved the “that’s what she said” video that you linked from the article. it was brilliant and funny.

  37. Thanks again for all the great feedback!

    I’m taking notes, and I’ll be posting blogs about user authentication, editing posts, and using AJAX with PHP and MySQL. Does anyone have anything else they’d like to see?

    Make sure you head over to my blog and subscribe to the RSS feed so you don’t miss them!

  38. Permalink to comment#

    I wouldn’t mind seeing how to build a basic image plug in using php and mysql.

  39. Permalink to comment#

    Awesome! neat and clean. calls for more ideas. thanks a ton.

  40. Nice tutorial to get me going for a CMS. I am a seasoned ColdFusion developer and took time last week to do the full immersion into php, so I could churn out smaller sites on much cheaper hosting. I do want to make a reusable CMS so i can easily drop it into future sites.

  41. Brian
    Permalink to comment#

    Thank goodness the people that write the major frameworks didn’t just rely on the existing frameworks. Simply using what everyone else has done isn’t a very good way to get new better stuff. It is one thing to keep improving on pre-existing code, but every now and then, starting from scratch is simply the best solution in order to use all of the latest techniques, and this is how you learn.

    Thanks for the tutorial.

  42. Hi i like this tutorial alot but i have one question ask. i am just starting web development the languages and i am wondering what is a better language to learn first? i was thinking of PHP or Ruby on Rails? I know that PHP is a scripting language and that Rails is a framework, which language would be the best to learn first in order to understand the other on?
    Please and thank you. :)

    • Ruby on Rails is a little easier — I’m pretty sure the whole goal of the project was to simplify back-end development.

      PHP will give you a better understanding of the how, if that’s what you’re looking for.

  43. Permalink to comment#

    thanks for the tutorial

  44. Permalink to comment#

    Hi, Chris.
    I don´t know when you do this!! Do you not sleep?

  45. No offense, but I had a quick look through your article and there’s a lot of things I have an issue with.

    Why are you doing the CREATE TABLE IF NOT EXISTS on every page load? It’s a bit of a useless query. Create it, and then store somewhere that it is created – or just do so manually.
    display_admin() form. $_SERVER['PHP_SELF'] is not safe. XSS exploitable. Clean it using htmlspecialchars($_SERVER['PHP_SELF'], ENT_QUOTES) or htmlentities($_SERVER['PHP_SELF']);
    If magicquotes GPC is on, you want to strip slashes from items in $_POST before inserting them to the database. (In most cases, magicquotes GPC will be disabled these days)
    In the INSERT query for inserting a new item, it’s best to specify the fields to insert into. If you add another column (for example with a default value) to the table then you’ll also need to adjust the query. If you’re explicitly naming columns, you don’t need to.
    mysql_num_rows should be used with care. It’s safe to use as you’re using it where you’ve got a LIMIT that is set very low on the query. Why? This function makes PHP count each and every row manually. The best solution (for large datasets) is to either to a COUNT query separately or even better, in the while loop, set a flag if any posts were processed or not. (Speaking of which, you could just do if(!$entry_display) { … no posts message }.
    You don’t need to use stripslashes when fetching the data from the database. Especially if magicquotes GPC is off, as this will strip legitimate slashes.
    Once again, $_SERVER['PHP_SELF'] is tainted. This is especially important here, as it’s a publicly accessible page. Escape it before displaying it.
    if($_POST) is a very bad check to be doing. Check if $_SERVER['REQUEST_METHOD'] is POST, or $_POST is not empty (if(!empty($_POST)) {)

    Sorry, but there’s this issue I have if you’re going to be teaching other people how to use a programming language – you need to do it right, so you’re not teaching bad practices.

    • Thanks for pointing out holes in the script. In any further installments of this series, I’ll make the fixes you mentioned to ensure safe code.

      I’m still learning, so I apologize for my faux pas. I assure you they were unintentional. :)

  46. Great job Jason Lengstorf!

    I think this article is very well done and will prove to be a great help to many ambitious web heads!

    I was commissioned to build a custom web app for a client recently (Dec. 08). I knew I was going to have to work with some kind of CMS framework and create, read, update, and delete a lot of data that the CMS framework couldn’t do; due to the custom nature of the project.

    So I spent a week going through a very nice tutorial over at lynda.com (no plug intended) on how to build a CMS with PHP and MYSQL. Now I have a better understanding for how PHP/MYSQL/CMS work and was able to write some of my first functions with ease. BUT, I think this article would have saved me a lot of time; had I read it prior to my project.

    Great job guys!

  47. tim
    Permalink to comment#

    not to rain on the parade, but the display_public() is terrible. In the same function you have data access, business logic, and templating logic. Don’t get me wrong, your post is probably interesting for PHP newbies, but it teaches bad practices. Use with caution.

  48. Thanks Chris… Every PHP beginner would love this..

  49. Nice, what’s the name of the set of Icons used in this tut? I love the look of them!

  50. lowell
    Permalink to comment#

    Caught this on popurls.

    I heart heredoc. Well, in Ruby. Same thing, though. Heredoc rocks.

  51. Permalink to comment#

    Great post, Jason. Thanks very much! I’ve been thinking about making my own CMS for a while, but don’t really know where to start. Would be great if you expanded on this – making a more comprehensive CMS?

    • After all the great feedback on this tutorial, I’m thinking I’ll start a series of articles that go over some of the different aspects of building a CMS. I’ll start here and build on this model to allow for image uploading, user authentication, and all that good stuff. Make sure you grab my RSS feed or follow me on Twitter!

    • craig
      Permalink to comment#

      Sounds good, I’ll definitely be following along.

  52. mohamed
    Permalink to comment#

    very much appreciated. Thanks!

  53. lan
    Permalink to comment#

    Jason Lengstorf,thanks ! but can you write the delete and edit method for this demo?

    thanks again!

  54. Kai
    Permalink to comment#

    Hi Jason,

    There is something I don’t understand about the code. I see ‘var $host’ which is confusing to me. I don’t recall PHP using var. I know JavaScript uses var, but what is the purpose of it here?

    Is it doing something…? Some convention?

  55. adam
    Permalink to comment#

    PHP sucks….

    Rails rocks. you can do this with commenting in 10 minutes in rails.

    • RoR FTW!!!

    • Mr. X
      Permalink to comment#

      You’re an idiot. PHP is a great web programming language – going around running and telling people to use Rails instead will only cause confusion with beginners. You don’t use Rails to make scripts for a few simple pages, and it sure as hell isn’t the only option available. And there’s absolutely nothing wrong with using PHP – check out CakePHP.

  56. Ron
    Permalink to comment#

    Thank you. It’s helpful. I’m going back to using PHP after a long break.
    I am getting an error when running your code on my server:

    Notice: Undefined index: admin
    pointing to this line:
    echo ( $_GET['admin'] == 1 ) ? $obj->display_admin() : $obj->display_public();

    I do not get this error while I use the demo (on your server).

    Any idea why?

  57. thanks for this nice article. I finished studying PHP and SQL from some books and w3schools. i got some good knowledge, now i am searching internet for developing my first site, your article is helpful, thanks.

  58. Mr. Magic
    Permalink to comment#

    Another reason why people who don’t know what they’re doing should not try telling others how to write code.

    1: Uses var with public. var = PHP4 and public = PHP5 syntax

    2: Does not follow any established coding standard (ie. PEAR standard)

    3: Class used basically as a wrapper for procedural functions

    4: As pointed out, the code isn’t separated at all.

    5: Using if to check if a array index exists will cause a warning, should use isset() instead

    6: Builds DB on every request (as pointed out earlier)

    Seeing it’s not exactly an advanced article, most of the newbie problems in the code could be ignored, but they should at least be pointed out. How will a beginner know that this code blows, and that they should seek more education, unless you tell them?

  59. Great article, I’m liking the beginners to your first cms, but it really is just to basic. It doesn’t really follow a MVC pattern at all which most of the time all CMS’s now of days follow. You incorporate the html inside your html when you should be separating it. I get that it is for beginners, but your pushing them in the wrong direction, this should be more for “standards” in today’s coding and not the 10 years before now.

  60. Krasimir Kazakov
    Permalink to comment#

    Very bad coding style … you tried to make it look professional, but it doesn’t. You rely on few PHP flaws, ignore notices, instead using everything correctly. You even DON’T separate design from code.

    I really don’t recommend anyone using this code at all. Gives you bad example for being a programmer.

  61. Great tutorial. I’ve been thinking about learning PHP, good programmers are hard to find. :) Will pass on w/ a tweet.

  62. Adam
    Permalink to comment#

    Hey mate. Neat tutorial.
    Just a note, the “Build the Database” won’t compile because the heredoc closing identifier needs to be the first and only thing on the line, but it is tabbed in. no big deal, but php triggers the error “Parse error: syntax error, unexpected $end…”

  63. Peter
    Permalink to comment#

    Notice: Undefined index: admin in SimpleCMS\display.php on line 48

    Notice: Undefined variable: entry_display in SimpleCMS\_class\simpleCMS.php on line 30

    How do I solve this?

    • The way your server has notices set up is causing those errors. To correct the first, you just need to add a check if the variable is set in display.php:

      echo ( isset($_GET['admin']) && $_GET['admin'] == 1 ) ? …

      The other issue appears to be coming from the fact that I didn’t explicitly declare $entry_display before I started adding to it. To solve it, just declare $entry_display = ”; right below the start of the display_public function.

      Hope that helps!

  64. HansF
    Permalink to comment#

    Being a relative php/mysql beginner (after a year of leisurely coding) I still don’t understand why mysql is so slow.

    I guess with the simple code in the tutorial the whole process will be fast, but once you reach complexity levels like WordPress I find the speed is not what I imagined it to be. Sure, if you host your site/blog with your ISP, or have a fast company intranet server then I assume it will be fine. But not on my Atom 230/2GB RAM home server.

    I did a lot of research on why this was and the bottle-neck was always mysql, not php. So what about a simple CMS without a database, or one with a lightweight database? Still, nice tutorial, especially the oophp part, which I haven’t touched before. –Hans

  65. mario
    Permalink to comment#

    This is far from a useful introduction to PHP. It is an amateurish introduction to PHP.

    One of the banes of PHP programming are SQL injections. They arise from using string concatenation and the often-forgot escaping. (Which the author obviously did.)

    If you want to get a real introduction to PHP and MySQL, go look for an article about PDO or SQL prepared statements. It’s safer and easier.

  66. Joel L
    Permalink to comment#

    In this day and age, security is very important. Any ‘my first php ___’ tutorial needs to cover this, given the legacy of shit code and shit tutorials.

    You need to be using prepared statements and parametrized queries. This allows you to easily do data validation and sanitize the input. Escaping and stripping won’t cover all your bases. This tutorial leaves the end user wide open to both SQL injection and XSS.

    Mysqli is a good module for this. The best part is that it’s built in to sql 5 and greater. There is no excuse for raw queries.

  67. Permalink to comment#

    A very nice tutorial. simple and to the point. I also like the design of your site. Just curious, what CMS are you running for your site ? Or is your site entirely custom built from grounds up ?

  68. Derek Paul
    Permalink to comment#

    While I appreciate the introduction to this, my main issue with this tutorial is that it doesn’t explain why you’re doing any of this stuff. For example, I understand that “$this” is obviously a variable but why are we writing “$this->” before every single part of the database call? This isn’t a tutorial as much as it’s a “copy what I’m doing blindly to get the exact same outcome as me”. I’ve used and written in PHP before so I have a basic understanding, but some clarification as to the why of things is just as important to me as the how of them.

    Just my 2c.

  69. Sean
    Permalink to comment#

    I’m sorry, but this is really a god awful introduction to the world of PHP, and Chris should remove this article altogether. This was written by someone lacking experience, who has many bad habits, and is passing those bad habits onto unsuspecting beginners.

    • Derek Paul
      Permalink to comment#

      It’s not god awful as it’s not meant to be a encyclopaedic introduction to building a CMS with PHP/MySQL but it’s not exactly teaching anything. In that regard, I do think it’s not doing justice to beginners.

  70. Thank G-d for WordPress!

  71. Jorge
    Permalink to comment#

    I think this is NOT for beginners. There are a lot of stuff that I don’t understand and you should have explained it if the tutorial would be really for beginners:
    For example: When to use { } or [ ] symbols, when to use the ;
    What is the “$r = or $q=, or $p ” are those variables or are part of php language?

  72. Jonas
    Permalink to comment#

    All I’ve seen so far is bashing for this tutorial; could some wise coder please post a list of GOOD resources, i.e. tutorials focusing on good PHP coding practices, good security, how to separate code from HTML, etc?

    Thank you very much!

  73. kdawg
    Permalink to comment#

    man people just love to sit back and piss on others’ code. it’s a good, solid intro to a couple of popular technologies, back off.

    that said, i have a question! i’m getting the following error when attempting to load display.php:

    Parse error: parse error, expecting T_STRING' orT_VARIABLE’ or `T_NUM_STRING’ in C:\www\simpleCMS\_class\simpleCMS.php on line 69

    line 69 reads:

    if ( ($p['title']) )

    i’ve tried both “!empty(…)” and “isset(…)” to make sure $p['title'] is kosher, but the same error occurs. it looks like it’s needing some sort of type declaration, which seems odd for a loosely typed language. any ideas?

    thanks.

    • Someone mentioned that the source code had the end of a HEREDOC statement tabbed in, which would cause the code to break. Check display_admin() and make sure that the closing delimiter (“ADMIN_FORM”) doesn’t have any white space in front of it.

      And, also, if you’re planning on using this code for anything beyond learning, it would do you well to check out security measures like mysqli or PDO. SQL injection is nasty. You can read about it here.

  74. very nice info for beginners.

  75. Permalink to comment#

    I hate to say it but i was a with Mysql and PHP and then i discovered the drewamwevaer functions to create quick CMS’s neewbee

    Once you gte going it never ends and you can do a lot with a simple GUI, i know that there are purists who would never leave note pad but for a beginner its a great start

  76. joe
    Permalink to comment#

    what an awful piece of shit code is this? Fail !

  77. I’ve learned just enough PHP and MySQL to get by. Looking forward to the rest of this series – especially displaying and editing and saving changes.

  78. Permalink to comment#

    very nice info for beginners.

  79. this is not for beginners thats sure…

  80. Permalink to comment#

    Thank u very much for the great tutorial, and keep em coming!

  81. Corey
    Permalink to comment#

    I’m personally concerned that your CMS displays the admin FORM based on a GET var being set to 1. You should, at a minimum, propose that a key value (password) be set by the admin and used instead.

  82. Thanks for this easy to understand PHP/MySql titorial :)

  83. This is great and a lot of help.
    keep it up.

  84. Permalink to comment#

    Jason Lengstorf,thanks ! but can you write the delete and edit method for this demo?

    thanks again!!

  85. Permalink to comment#

    This was a really useful article, well written and well presented. Do you think perhaps that using classes and functions so early on was a bit too much for some of the newer users to php mysql ?

  86. Mike
    Permalink to comment#

    Guys, CMS It’s a good concept . Thank you. Please if you going to talk about Database, consults a DBA or someone who knows Databases. You are confused about a Databases and a Tables. Using MySQL, you can have many Databases. Databases are used to group tables that are related. A table is not a Database. A Database is not a Table. I hope this helps.

  87. Permalink to comment#

    Thank goodness the people that write the major frameworks didn’t just rely on the existing frameworks. Simply using what everyone else has done isn’t a very good way to get new better stuff. It is one thing to keep improving on pre-existing code, but every now and then, starting from scratch is simply the best solution in order to use all of the latest techniques, and this is how you learn.

    Thanks for the tutorial..

  88. Peter
    Permalink to comment#

    To all the negative people who posted bad comments. It’s easy to be negative but you yourselves could not actually write any better code becuas eif you could then do your own framework and tell us about it.

  89. Permalink to comment#

    Thanks for the tutorial!

    A friend and I have been developing site using CMS’s and while he understands php, I do not. This was a great way to understand the db connections that take place and how to add/display db content using php.

    Thanks again,
    Chris

  90. Adam
    Permalink to comment#

    I think the tutorial was a decent example of what can be constructed with simple PHP and MySQL.

    It is really ironic that so many people are shouting that it is horrible without recommending any tutorial in its place. :/ If you want to bash it, why not at least offer an alternative?

  91. Permalink to comment#

    Good stuff thanks.

  92. ramesh kuwnar
    Permalink to comment#

    thanks man, it helps me to learn cms based project….

  93. Permalink to comment#

    I really like this, can wait to read more, maybe edit and put in some ajax, like small tut which includes everything.

  94. zaw
    Permalink to comment#

    its so cool! thanks for it Jason!

  95. Permalink to comment#

    Can I translate this tutorial?

  96. lamparrr
    Permalink to comment#

    awesome…..
    thanks brother.

  97. I really don’t understand why anyone would wanta build their own cms instead of just extending drupal or something already out there

  98. jasn
    Permalink to comment#

    Sorry to chime in with the negativity, but I feel if you are teaching how to write a basic CMS, then some more things need to be mentioned. (I won’t go into some of the other things mentioned already)

    OOP – You note that it is good practice to use OOP, but you are not using OOP effectively in your example nor teaching it correctly. When users begin learning about furthering OOP practices and trying it out on your example, they will get frustrated because it doesn’t work. You have a super class that combines alot of functions. You can’t extend this class like so:

    class blah extends simpleCMS { }

    SELECT * FROM… is slow and bad practice. Start new users right! When your application gets bigger then your mysql queries will take longer because mysql has to search through the entire table to get the 1 (or 2) things you need. Try:

    SELECT title, bodytext FROM….

    Why did you user HEREDOC instead of echoing strings or breaking out of PHP?
    Curly braces should be always be used. Google “PHP Coding Standards” or I recommend this from Evolt.org

  99. jasn_001
    Permalink to comment#

    My comment got lost in cyberspace so I will recreate it (quickly).

    On the article, I will not mention some of the previous comments but:
    – OOP. Cleaner code and good practice – if done right. If you are going to show a technique, please utilize it correctly. If any of these users study more into OOP, hen they would be disappointed to see thy cannot fully utilize what you have taught them.
    – SQL. SELECT * FROM.. is slow and bad practice when your application gets bigger. Please use SELECT this, that FROM.. instead, you don’t want to do full table searches.

  100. why all is in php why not asp.net i think its far better then php, now i dont want to learn again a new language. please also give some asp.net exp

  101. great articles. good thing i stumbled your site.thanks for sharing this helpful site.thumbs up!

  102. Suyanthan
    Permalink to comment#

    Hi SIr,
    This is really a super php class exam!. I was searching for this last few days and finally got it!!

    Thank you very much!!!

  103. The Smart One
    Permalink to comment#

    It’s a nice piece.

    Security is not a relevant topic for beginners trying to learn how to do things. Let’s be realistic, do you really think a newbie stumbled on to this tutorial to develop an online banking platform? (Wouldn’t shock me, actually, but I doubt this was the writer’s target).

    A newb is more likely to build a little “Hello World” site or display pictures of his kids using this. So it is open to SQL injection, sure… but when the newb finds that PedoBear has been superimposed into the photos of his kids, he will hone his security skills.

    Any serious developer takes a more robust course on professional development, followed by occasional security refreshers. Everyone knows this.

    Now… No one who works with open source technologies should dare bash another for freely sharing knowledge. Ever. Correct mistakes out of respect for the readers, but don’t bash the author. He’s merely trying to contribute to the community. That’s what open source is all about.

  104. Emmauel
    Permalink to comment#

    I like your style of dishing it out.
    Thanks a lot ..
    Te world need people like you.Good job

  105. KRAD
    Permalink to comment#

    your buildDB(); is creating a table and not a database isn’t it ?? And your var table is actually a database ???

  106. Permalink to comment#

    Great tutorial. The OOP approach is definitely the way forward. I will be using this technique in my first big php project

  107. fenser
    Permalink to comment#

    Nice tutorial. I’m gonna implement the CLASS techniques to place my PHP codes, cause it makes my HTML code messy seeing a lot of PHP inserts..lol…but this post was likely 3-4 years ago..i noticed it uses the old MySQL_* …using this in your SQL code is not safe and deprecated for higher PHP versions as someone told me…I reccommend using the MySQLi_* or PDO..(more about MySQLi_* implementation at W3Schools.com)..this have security passes better compared to the old one…cause it’s not already maintaned..I just updated to using the new one…So I am expecting more PHP techniques here mostly on SQL injections cause this is a very big issue to those developers like me who do not depend on using Frameworks….nice site..i’m gonna bookmark it…

  108. Anon
    Permalink to comment#

    Please do not follow this tutorial and find a much more recent one.

    Please note that this tutorial is extremely old and uses obsolete methods (such as the mysql_* functions – you need to use mysqli_* or PDO instead).

    This site would be doing the internet a favour if they completely removed this tutorial from their site.

Leave a Comment

Current day month ye@r *

*May or may not contain any actual "CSS" or "Tricks".