📖 PHP Building Dynamic Pages

Building dynamic pages with PHP can vary depending on the goals of the page, but there are some patterns that help keep code duplication to a minimum. Generally speaking, as much process as possible should be done early before generating any HTML. If possible, it can be beneficial to delay assembling the HTML until after all page processing is complete.

Page Displays

Many times the page build will depend on the source of the information that's being loaded. Page content can be hard coded into the page, loaded from a database record or collected from a web form completed by the user. This means the page process must look for these sources and determine the type of content to be loaded. A second and just as important issue is how the page should be displayed. This is a "form follows function" kind of test. If you are trying to provide informational displays like typical web pages, you will design the page differently than if you are trying to provide a means for updating web content.

  • Select lists for users to choose saved items.
  • Page load for specific content from database.
  • Form for editing existing records or collecting information for a new record.
Content Sources
  • Hard coded into page.
  • User input from web form.
  • Saved content from database.

The details of how to design page layouts and collect information from different sources are covered in other articles. I want to explain the approach to processing user input with this variety of options. We will need to create specific triggers in our forms and check for those triggers to control the page processing. Below is an example of the code pattern to achieve this result.

Create Blog Table

See the example below for the code to create a new blog table with the following columns and data attributes. Don't forget to insert a couple of posts for testing purposes.

  • Post ID - numeric (int) unique record identifier - generated automatically by MySQL
  • Title - variable character - length(max 75 characters) - Cannot be Null
  • Content - text - length(max 65,535 bytes) - Cannot be Null
  • Publish - Boolean - Default 0 (false)
  • Author ID - numeric (int) - Cannot be Null
  • Timestamp - Auto saved by db
Example
-- Table structure for table `blog`
--

CREATE TABLE IF NOT EXISTS `blog` (
	`postID` int(11) NOT NULL AUTO_INCREMENT,
	`postTitle` varchar(255) NOT NULL,
	`postContent` text NOT NULL,
	`publish` tinyint(1) NOT NULL DEFAULT 0,
	`authorID` int(11) NOT NULL,
	`created` timestamp NOT NULL DEFAULT current_timestamp(),
	PRIMARY KEY (`postID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Back end db for Blog';

PHP Page Set Up

  1. Include dependencies (config.php)
  2. Initialize variables
  3. Check for data submission (POST and/or GET)
  4. Process form
  5. Query database
  6. Assemble HTML content and template

The first page is designed for public access to the blog. We will list the blog posts in a single page with links to the individual blog posts.

To begin, we set up our blog list page by accessing the blog posts from the database. We will need a script to manage the interactions betweeen our page and the data as well as a way to generate the needed HTML.

To complete these tasks, we are going to use a method of development known as MVC. MVC stands for Model, View, Controller. Basically, the Model is the database, the view is the HTML and the Controller is the code that coordinates and processes the user inputs.

Using the list above, the first 4 items are really Controller elements. #5 is the Model and #6 the View. In the example I am providing below, I have removed much of the Controller process into functions. These functions will be stored in the config.php file and called as we need them. The functions will take the user input and send a query to the database to assemble our page content.

Example Page Script
<?php
// load config.php to connect to the database
include_once 'config.php';

// initialize variables
$pageContent = NULL;

// check $_GET for postID to load a single post
if (filter_has_var(INPUT_GET, 'postID')) {

	// get the postID from the query string
	$postID = filter_input(INPUT_GET, 'postID');

	// call the blogPost function from config.php
	$postData = blogPost($conn, $postID);

	// pull the values from the array returned by the blogPost() function
	$postTitle = $postData[0];
	$postContent = $postData[1];

	// assemble the HTML
	$pageContent = "<h2>$postTitle</h2>
	$postContent\n
	<p><a href='blog.php'>Back to Blog</a></p>";

} else { // load the default blog list

	// initialize the list
	$postList = "<ul>";
	// call the blogPosts function from config.php
	$postListData = blogPosts($conn);
	// build the list from the multidimensional array returned by blogPosts() function
	foreach ($postListData as $blogPost) {
		foreach ($blogPost as $postID => $postTitle) {
			if($postID == 0) { // list error message returned from function
				$postList = <<<HERE
			<p>$postTitle</p>
HERE;      
			} else { // build the blog post list
			$postList .= <<<HERE
			<li><a href="blog.php?postID=$postID">$postTitle</a></li>
HERE;
			}
		}
	}
	// close the list
	$postList .= "</ul>";

	// assemble the HTML
	$pageContent = <<<HERE
		<h2>Daily Blog Selections</h2>
		<p>Please select a blog post below.</p>
		$postList
HERE;

}

$pageTitle = "My Blog";
include 'template.php';
?>

Notice in this script there are no direct calls to the database, but there are a couple of custom functions called blogPost() and blogPosts(). You might guess what each function does from their names. The blogPost() function returns the contents of a blog post given the postID in an array. The blogPosts() function returns a list of blog posts in a multidimensional array.

The config.php file contains the functions used to connect to the database. The code for running the blog queries is below. You can copy and paste this code into your config.php file (after the db connection script) to see if you can make this work.

Example Functions Script
// this function returns the contents of a blog post given its postID
function blogPost($conn, $postID) {
	$stmt = $conn->stmt_init();
	if ($stmt->prepare("SELECT postTitle, postContent FROM blog WHERE postID = ?")) {
		$stmt->bind_param("i", $postID);
		$stmt->execute();
		$stmt->bind_result($postTitle, $postContent);
		$stmt->fetch();
		$stmt->close();
	}
	$postData = array($postTitle, $postContent);
	return $postData;
}

// this function returns a multidimensional array of blog post IDs and titles
function blogPosts($conn) {
	$stmt = $conn->stmt_init();
	if ($stmt->prepare("SELECT postID, postTitle FROM blog")) {
		$stmt->execute();
		$stmt->bind_result($postID, $postTitle);
		$stmt->store_result();
		$classList_row_cnt = $stmt->num_rows();
		if($classList_row_cnt > 0) { // make sure we have at least 1 record
			while($stmt->fetch()) { // loop through the result set
				// array for each record
				$postData = [$postID => $postTitle];
				// add each record to the multidimensional array
				$postListData[] = $postData;
			}
		} else { // no records in the db
			$postData = [0 => "There are no posts at this time."];
			$postListData[] = $postData;
		}
		$stmt->free_result();
		$stmt->close();
	} else { // db connection error
		$postData = ["The blog is down now. Please try again later."];
		$postListData[] = $postData;
	}
	return $postListData;
}