Cache Dynamic HTML Pages in PHP (A Simple Example)

Welcome to a tutorial and quick example on how to cache dynamic HTML pages in PHP. So you want to improve the performance of a PHP project that generates HTML pages dynamically?

We can create a simple caching system in PHP by working with output buffering:

  • Load the cached HTML page if it exists – if (file_exists("cached.html")) { require "cached.html"; }
  • else - Save the generated page into a static HTML file.
    • ob_start();
    • require "your-scripts.php";
    • file_put_contents("cached.html", ob_get_contents());
    • ob_end_flush();

That covers the basic idea, but read on for a more detailed example!

ⓘ I have included a zip file with all the 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.

 

 

TABLE OF CONTENTS

 

DOWNLOAD & NOTES

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

 

QUICK NOTES

If you spot a bug, feel free to comment below. I try to answer short 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.

 

EXAMPLE CODE DOWNLOAD

Click here to download all the example 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.

 

 

CACHING HTML PAGES IN PHP

All right, let us now get into the example of caching dynamic HTML pages in PHP.

 

STEP 1) DUMMY CONTENT TABLE

1-content.sql
-- (A) CONTENT TABLE
CREATE TABLE `content` (
  `content_id` bigint(20) NOT NULL,
  `content_title` varchar(255) NOT NULL,
  `content_body` longtext NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
ALTER TABLE `content`
  ADD PRIMARY KEY (`content_id`);
 
ALTER TABLE `content`
  MODIFY `content_id` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;

For this example, we will work with this simple content table with only 3 fields.

  • content_id Primary key, auto-increment.
  • content_title Title of the page.
  • content_body Main contents of the page.

 

 

STEP 2) HTML TEMPLATE

2A) TOP HALF OF THE PAGE

2a-page-top.php
<!DOCTYPE html>
<html>
  <head>
    <title><?=$_PAGE["content_title"]?></title>
  </head>
  <body>
    <header>My Site</header>
    <main>
      <h1><?=$_PAGE["content_title"]?></h1>
      <?=$_PAGE["content_body"]?>
    </main>

 

2B) BOTTOM HALF OF THE PAGE

2b-page-bottom.php
    <footer>Copyright, My Site.</footer>
  </body>
</html>

Next, we have a simple HTML template to show the content. Of course, your project can be a lot more complex with dynamic menus, sidebars, footers, and such.

 

STEP 3) GENERATING A DYNAMIC HTML PAGE

3-dynamic.php
<?php
// (A) DATABASE SETTINGS - CHANGE TO YOUR OWN
define("DB_HOST", "localhost");
define("DB_NAME", "test");
define("DB_CHARSET", "utf8mb4");
define("DB_USER", "root");
define("DB_PASSWORD", "");

// (B) CONNECT TO DATABASE
$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
]);

// (C) GET CONTENT FROM DATABASE
$id = 1; // CONTENT ID 1
$stmt = $pdo->prepare("SELECT * FROM `content` WHERE `content_id`=?");
$stmt->execute([$id]);
$_PAGE = $stmt->fetch();
 
// (D) GENERATE HTML PAGE
require "2a-page-top.php";
require "2b-page-bottom.php";

This is the “usual stuff”. Where we fetch data from the database and generate the dynamic HTML page.

P.S. Remember to change the database settings to your own.

 

 

STEP 4) SIMPLE PHP CACHING

4-cache.php
// (A) SERVE STATIC HTML IF EXIST
$id = 1; // CONTENT ID 1
$file = "cached-$id.html";
if (file_exists($file)) {
  // echo "THIS IS A CACHED COPY!";
  require $file;
}
 
// (B) GENERATE HTML FILE
else {
  // (B1) START OUTPUT BUFFERING
  ob_start();
 
  // (B2) GENERATE HTML PAGE
  require "3-dynamic.php";
 
  // (B3) SAVE BUFFER INTO STATIC HTML
  file_put_contents($file, ob_get_contents());
 
  // (B4) OUTPUT CONTENTS
  ob_end_flush();
}

That’s right – This is the same as the introduction snippet. We use output buffering to help us generate the flat HTML file – Serve it in the future if it exists.

The end. This should help with the performance – Loading from a static HTML file is definitely way faster than loading from the database, and regenerating all those dynamic sections.

 

 

EXTRA BITS & LINKS

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

 

EXTRA) CACHING DATA

Yes, we can, technically cache other “raw data” with this technique too. For example, getting a list of products.

if ($_POST["request"] == "getAll") {
  if (file_exists("products.json")) { require "products.json"; }
  else {
    LOAD DATA FROM DATABASE
    OUTPUT BUFFER, SAVE, AND SERVE AS ABOVE
  }
}

 

APACHE & MYSQL CACHING

Lastly, before the “code master angry troll things” start to comment “this is stupid” – Caching is built straight into many of the major web servers and even MySQL. If you have direct access to the server, it will make more sense to just set these up.

 

THE END

Thank you for reading, and we have come to the end. I hope that it has helped you to better understand, 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 *