4 Steps Simple Barebones CMS With PHP MYSQL – Free Download

Welcome to a quick tutorial on how to create a simple content management system (CMS) with PHP and MYSQL. Looking to challenge yourself or just want a really simple CMS for your current project?

A barebones CMS will only require the following components:

  1. A database to store the page title and contents.
  2. PHP library to manage (save/load) the contents.
  3. A page to manage and update the contents.
  4. A page to load and display the contents.

Well, an actual example will better explain things. Let us walk through one in this guide – Read on!

ⓘ I have included a zip file with all the example source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

 

QUICK SLIDES

 

TABLE OF CONTENTS

Download & Notes Simple CMS Useful Bits & Links
Tutorial Video The End

 

 

DOWNLOAD & NOTES

First, here is the download link to the example source code as promised.

 

EXAMPLE CODE DOWNLOAD

Click here to download the source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

QUICK NOTES

  • Create a dummy database and import 1-database.sql.
  • Change the database settings in 2-lib-content.php to your own.
  • Launch 3-save.php in your browser, enter any title and text.
  • Launch 4-load.php in your browser, see how the page is rendered from the database.

If you spot a bug, please feel free to comment below. I try to answer questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

 

BAREBONES CMS

All right, let us now get started with the barebones CMS in PHP and MYSQL.

 

STEP 1) CONTENT DATABASE TABLE

1-database.sql
CREATE TABLE `contents` (
  `content_id` int(11) NOT NULL,
  `content_title` varchar(255) NOT NULL,
  `content_text` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 
ALTER TABLE `contents`
  ADD PRIMARY KEY (`content_id`),
  ADD KEY `content_title` (`content_title`);
 
ALTER TABLE `contents` ADD FULLTEXT KEY `content_text` (`content_text`);
  ALTER TABLE `contents`
  MODIFY `content_id` int(11) NOT NULL AUTO_INCREMENT;
Field Description
content_id The content ID, primary key.
content_title Title of the page.
content_text The contents of the page itself.

Yep, this one should be very straightforward, we need a table to store the title and content of the pages. Just a small note here though, the title and text are indexed – ADD KEY `content_title` and ADD FULLTEXT KEY `content_text`. This indexing will take up a little more disk space but greatly improves the search performance.

 

 

STEP 2) CMS CONTENT LIBRARY

2-lib-content.php
<?php
// (A) CONTENT CLASS
class Content {
  // (A1) CONSTRUCTOR - CONNECT TO DATABASE
  private $pdo;
  private $stmt;
  public $error;
  function __construct () {
    try {
      $this->pdo = new PDO(
        "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET,
        DB_USER, DB_PASSWORD, [
          PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
          PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
        ]
      );
    } catch (Exception $ex) { exit($ex->getMessage()); }
  }
  
  // (A2) DESTRUCTOR - CLOSE DATABASE CONNECTION
  function __destruct () {
    $this->pdo = null;
    $this->stmt = null;
  }
 
  // (A3) SAVE CONTENT
  function save ($title, $text, $id=null) {
    if (is_numeric($id)) {
      $sql = "REPLACE INTO `contents` (`content_id`, `content_title`, `content_text`) VALUES (?,?,?)";
      $data = [$id, $title, $text];
    } else {
      $sql = "INSERT INTO `contents` (`content_title`, `content_text`) VALUES (?,?)";
      $data = [$title, $text];
    }
    try {
      $this->stmt = $this->pdo->prepare($sql);
      $this->stmt->execute($data);
      return true;
    } catch (Exception $ex) {
      $this->error = $ex->getMessage();
      return false;
    }
  }
 
  // (A4) LOAD CONTENT
  function load ($id) {
    $this->stmt = $this->pdo->prepare("SELECT * FROM `contents` WHERE `content_id`=?");
    $this->stmt->execute([$id]);
    return $this->stmt->fetch();
  }
}

// (B) DATABASE SETTINGS - CHANGE THESE TO YOUR OWN!
define("DB_HOST", "localhost");
define("DB_NAME", "test");
define("DB_CHARSET", "utf8");
define("DB_USER", "root");
define("DB_PASSWORD", "");

// (C) CREATE NEW CONTENT OBJECT
$_CMS = new Content();

The core library may look a little intimidating at first, but keep calm and look carefully.

  • On creating the $_CMS = new Content() object, the constructor will automatically connect to the database; The destructor will automatically close the database connection when the object is destroyed.
  • There are only 2 functions here – function save() to save page contents, and function load() to get the page contents.

That’s all, but a small reminder here to change the database settings to your own again.

 

 

STEP 3) UPDATE CONTENT PAGE

3-save.php
<?php
// (A) LOAD LIBRARY
require "2-lib-content.php";
$id = 1; // FIXED TO 1 FOR SIMPLICITY

// (B) SAVE CONTENT WHEN FORM IS SUBMITTED
if (isset($_POST['title'])) {
  echo $_CMS->save($_POST['title'], $_POST['text'], $id)
  ? "<div>CONTENT UPDATED</div>"
  : "<div>".$_CMS->error."</div>" ;
}
 
// (C) EDIT PAGE
$content = $_CMS->load($id); ?>
<form method="post" id="pageForm">
  <label for="title">Title</label>
  <input type="text" name="title" required
         value="<?=$content==false?"":$content['content_title']?>"/>
  <label for="text">Content</label>
  <textarea name="text" required><?=$content==false?"":$content['content_text']?></textarea>
  <input type="submit" value="Save"/>
</form>

Right, this page is seemingly complicated again, but let’s walk through it:

  1. Self-explanatory. Loads the PHP library, but we fix the content ID to $id = 1 in this demo to keep things simple.
  2. Save or update the content when the form is submitted.
  3. The HTML form to update the content itself.

That’s all for the essentials behind this “one-page admin”.

 

 

STEP 4) DISPLAY CONTENT PAGE

4-load.php
<?php
// (A) GET PAGE CONTENTS FROM DATABASE
require "2-lib-content.php";
$id = 1; // FIXED TO 1 FOR SIMPLICITY
$content = $_CMS->load($id);
 
// (B) OUTPUT HTML ?>
<!DOCTYPE html>
<html>
  <head>
    <title><?=$content['content_title']?></title>
  </head>
  <body><?=$content['content_text']?></body>
</html>

Now that we have some random contents in the database, the final step is to output it… This should not be a mystery anymore. We simply use $content = $_CORE->load($id) to fetch and output the contents.

 

USEFUL BITS & LINKS

That’s all for this guide, and here is a small section on some extras and links that may be useful to you.

 

HOW TO WORK WITH MULTIPLE PAGES?

The above barebones example works, but it only works with a single page. As for “how to manage multiple pages”, everyone probably has a different requirement. So I will not go into the exact details, here are a few general steps:

  • Add a new getAll() function in 2-lib-content.php, SELECT `content_id`, `content_title` FROM `contents`.
  • Use the getAll() function to build another admin page, list all the available content.
  • When the user clicks on the content, redirect to 3-save.php?id=N.
  • The rest should be straightforward. Modify 3-save.php and 4-load.php to follow $_GET['id'].

 

 

HOW TO SEARCH?

Want to add a new search feature?

  • Add a new search function to 2-lib-content.php.
  • Captain Obvious hint, do a SELECT * FROM `contents` WHERE `content_text` LIKE ?, and $this->stmt->execute(["%SEARCH%"]).

 

MORE FUTURE DEVELOPMENT

I know, multiple pages are not the only concern. There are many more areas you can work and improve on.

  • The <textarea> is too “raw” for a CMS. Check out TinyMCE, or do a search for your own preferred “What You See Is What You Get (WYSIWYG) Editor”.
  • Protect 3-save.php. Create a user login system, or at least put a basic HTTP authentication on it.
  • Of course, change 4-load.php to also load different pages, use your own HTML layout.
  • If you want a “URL slug” like WordPress or Drupal, feel free to add a “URL” field in the database. You will also need to work with htaccess, check out the pretty URL tutorial link below.

 

LINKS & REFERENCES

 

TUTORIAL VIDEO

 

THE END

Thank you for reading, and we have come to the end of this guide. I hope that it has helped you with your project, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

Leave a Comment

Your email address will not be published. Required fields are marked *