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
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
-- (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
<!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
<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
<?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
// (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!