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!

 

 

TABLE OF CONTENTS

 

DOWNLOAD & NOTES

Here is the download link to the example code, so you don’t have to copy-paste everything.

 

EXAMPLE CODE DOWNLOAD

Source code on GitHub Gist

Just click on “download zip” or do a git clone. I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

SORRY FOR THE ADS...

But someone has to pay the bills, and sponsors are paying for it. I insist on not turning Code Boxx into a "paid scripts" business, and I don't "block people with Adblock". Every little bit of support helps.

Buy Me A Coffee Code Boxx eBooks

 

 

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.

 

 

EXTRAS

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 *