Make PHP Sites

Last updated: 2015-09-13

Posting a forum thread

In this section, we'll go over how to allow a registered user to post a thread to a forum.

The code for this version will be written in a procedural method.

Requirements

Refer to the Get Started section to know what you need to use this tutorial. You must also have an understanding of HTML and how a web page is constructed.

Prerequisites

To use this tutorial, we recommend that you use our other lessons, User registration, User log-in and log-out, Setting restrictions with PHP and PHP forum - The database to be able to duplicate what we have.

The database described in those tutorials is necessary if you plan to follow this tutorial line-by-line. Only logged-in users will be able to post to this forum.

Contents

Database tables

Make sure you have created and understand the tables required to follow this lesson.

Table: forum_boards

Column Type Description
boardID INT (11) This will be the primary key. It is a unique ID number assigned to each individual board. It should be set to increment automatically.
board VARCHAR (250) This holds the name of the board.
isDeleted Bool A TRUE/FALSE value that will be used to control whether or not the board can be found.
timestamp Timestamp A time stamp, provided by the database, about time the board was last updated.

Table: forum_threads

Column Type Description
threadID INT (11) This will be the primary key. It is a unique ID number assigned to each individual thread. It should be set to increment automatically.
boardID INT (11) The identification number of the board each thread belongs to.
userID INT (11) The identification number of the user who created the thread.
title TEXT The string of text the user enters as the title of the thread. You can set it to a limited number of letters.
content LONGTEXT The string of text the user entered as the body of their thread.
comments INT (11) The number of comments a thread has received. The number should start out as 0
created INT (11) The numberic value of the time a thread was created
isDeleted Bool A TRUE/FALSE value that will be used to tell if a user has canceld there account or has been blocked.
timestamp Timestamp A time stamp, provided by the database, about time the thread was last updated.

The thread form

Only logged-in users will be able to view this form. So, let's use the lesson about setting user restrictions to allow only logged-in users to see the form. Create a php file for the web form which will provide logged-in user a way to post to the forum.

					<?php
						session_start();
						
						if(!isset($_SESSION['userID']) || !isset($_SESSION['email'])){
							header('Location: /login.php');
						}
					?>
				

That short piece of code will allow only logged-in users to access the web form. After that bit of PHP, add the HTML to make the form.

					<?php
						[...]
					?>
					
					<html>
						<head>
							<title>Post a thread</title>
						</head>
						
						<body>
							
							<h1>Post a thread</h1>
							
							<form action="" method="post">
								<p>
									Which board?
									<br/>
									<select name="boardID">
										<!-- board names will go here -->
									</select>
								</p>
								
								<p>
									Title
									<br/>
									<input type="text" name="title" />
								<p>
								
								<p>
									Thread
									<br/>
									<textarea name="content"></textarea>
								</p>
								
								<p>
									<button type="submit">Post thread</button>
								<p>
							</form>
							
						</body>
					</html>
				

Notice the section of the form select. This section will hold the names of the tables available for the user to post. We'll load the boards from the database.

This is what your page should look like so far if you are a logged-in user:

Picture of a page with an unfinished thread posting form

Getting the boards

We need to make a connection to the database and query the forum_boards table to list the tables for the user.

					<?php
						session_start();
						
						if(!isset($_SESSION['userID']) || !isset($_SESSION['email'])){
							header('Location: /login.php');
						}
						
						// Connect to the database
						
						// What's the address of your database?
						$database_host = 'localhost';
						
						// What's the username to connect?
						$database_user = 'root';
						
						// What's the password for that user?
						$database_password = 'password';
						
						// What's the name of the database?
						$database = 'social';
						
						// User the MySQLi class to connect to database
				        $mysqli = new mysqli($database_host, $database_user, $database_password, $database);
						
						// Query for the available forum boards
						$sql = "SELECT * FROM forum_boards WHERE isDeleted!=1";
						$query = $mysqli->query($sql);
						
						// User fetch_assoc() to get all the rows
						$boards = array();
						while($rows = $query->fetch_assoc()){
							$boards[] = $rows;
						}
					?>
					
					<html>
						[...]
					</html>
				

Notice the use of the while loop and fetch_assoc() in the code after the query. The function fetch_assoc() is built into the mysqli class. When used with the while loop, we can get multiple rows of data instead of a single row.

For example, if we hadn't used while, the variable $boards would have data similar to this:

					Array(
						[boardID] => 4,
						[board] => 'Mobile games',
						[isDeleted] => ,
						[timestamp] => 2020-02-20T11:07:43-05:00						
						)
				

Since we do use while and our database/query work correctly, our array $boards get each row added to it. $boards would look similar to this:

					Array(
						[0] => Array(
								[boardID] => 1,
								[board] => 'Console games',
								[isDeleted] => ,
								[timestamp] => 2020-02-20T11:07:43-05:00							),
						[1] => Array(
								[boardID] => 2,
								[board] => 'Handheld games',
								[isDeleted] => ,
								[timestamp] => 2020-02-20T11:07:43-05:00							),
						[2] => Array(
								[boardID] => 3,
								[board] => 'Computer games',
								[isDeleted] => ,
								[timestamp] => 2020-02-20T11:07:43-05:00							),
						[3] => Array(
								[boardID] => 4,
								[board] => 'Mobile games',
								[isDeleted] => ,
								[timestamp] => 2020-02-20T11:07:43-05:00							)
					)
				

Now that we have all of the boards, we can list them in the <select> form element.

					<?php
						[...]
						
						// User fetch_assoc() to get all the rows
						$boards = array();
						while($rows = $query->fetch_assoc()){
							$boards[] = $rows;
						}
					?>
					
					<html>
						[...]
							<p>
								Which board?
								<select name="boardID">
									<?php foreach($boards as $board): ?>
										<option value="<?php echo $board['boardID']; ?>"><?php echo $board['board']; ?></option>
									<?php endforeach; ?>
								</select>
							</p>
						[...]
					</html>
				

Alternative syntax

Let's take a look at the <select> form element and what's going on within in. Notice the PHP script foreach. We're using something called alternative syntax, a slightly different way to write PHP within HTML.

Using the foreach loop, we're listing all of the boards in the <select> form element automatically instead of typing them out by hand. Imagine if you had 25 boards or more instead of just 4.

					<?php foreach($boards as $board): ?>
						<option value="<?php echo $board['boardID']; ?>"><?php echo $board['board']; ?></option>
					<?php endforeach; ?>
				

Since it's injected within HTML and with HTML in between instead of outside of it (like the code about <html>) we are formatting it a little differently. Instead of using {} braces to mark the start and end of a functionl we're using : and endforeach; to mark the start and end. It can work either way, with {} or : endforeach;.

If the foreach loop and query are working correctly, your page could look like this with values in the <select> form element:

Picture of web form with values in the select box

Adding a thread

So far, we've guaranteed that the user is logged in and loaded the available boards for them to post a thread. Now, let's allow them to post a thread. We want to make sure that they provide both a title and a thread message. Nothing more needs to be done to the form.

We'll add to the PHP to check and see if a form has been submitted with filled-in values. Use trim() to make sure the values aren't just blank spaces. If either of them is blank, don't let the thread be posted and deliver an error message.

					<?php
						session_start();
						
						if(!isset($_SESSION['userID']) || !isset($_SESSION['email'])){
							header('Location: /login.php');
						}
						
						[...]
						
						// User the MySQLi class to connect to database
				        $mysqli = new mysqli($database_host, $database_user, $database_password, $database);
						
						[...]
						
						// If the form was submitted
						if(!empty($_POST)){
							// Make sure that the values aren't blank
							$title = trim($_POST['title']);
							$content = trim($_POST['content']);
							
							if($title == '' || $content == ''){
								$error = 'You must enter both a title and a thread.';
							}
							else {
								// Post thread
							}
						}
					?>
					
					<html>
						[...]
						
						<?php
							if(isset($error)){
								echo $error;
							}
						?>
						
						[...]
					</html>
				

Successful post

If the user provided the necessary information, let's post the thread to the database. We'll need to add an INSERT query to our PHP. When the thread is inserted, we'll send the user to view that thread.

					<?php
						session_start();
						
						if(!isset($_SESSION['userID']) || !isset($_SESSION['email'])){
							header('Location: /login.php');
						}
						
						[...]
						
						// User the MySQLi class to connect to database
				        $mysqli = new mysqli($database_host, $database_user, $database_password, $database);
						
						[...]
						
						// If the form was submitted
						if(!empty($_POST)){
							// Make sure that the values aren't blank
							$title = trim($_POST['title']);
							$content = trim($_POST['content']);
							
							if($title == '' || $content == ''){
								$error = 'You must enter both a title and a thread.';
							}
							else {
								// Post thread and santitize data
								$title = $mysqli->real_escape_string($title);
								$content = $mysqli->real_escape_string($content);
								
								// Get the userID from the $_SESSION array
								$userID = $_SESSION['userID'];
								
								// Get the current time according to the server
								$time = time();
								
								// Get the boardID thanks to the select box
								$boardID = $_POST['boardID'];
								
								$sql = "INSERT INTO forum_threads (boardID, userID, title, content, created) VALUES(" . $boardID . ", " . $userID . ", '" . htmlentities($title) . "', '" . htmlentities($content) . "', " . $time . ")";
								$query = $mysqli->query($sql);
								
								// Get the thread's ID number
								$threadID = $mysqli->insert_id;
								
								// Redirect the user to the the thread page with the thread's ID
								header('Location: /forum/thread.php?threadID=' . $threadID);
							}
						}
					?>
					
					<html>
						[...]
					</html>
				

So what's going on in the new block of code? First, we're retrieving the user's ID from the $_SESSION array. We need that to identify the author of the thread. Then, we're using PHP's time() to get the current time. time() is an integer.
For example, the current time() value is 1582214863. We can use that integer to show the date any way we would like later on.

Notice the function htmlentities() holding the title and the content. That protects the database from problems with the string while it tries to run the query. It's necessary to allow things like hyphens and apostrophes to come in the title and content.

The function header() will send the user to the file we'll use to show a single thread.

All the code

					<?php
						session_start();
						
						if(!isset($_SESSION['userID']) || !isset($_SESSION['email'])){
							header('Location: /login.php');
						}
						
						// Connect to the database
						
						// What's the address of your database?
						$database_host = 'localhost';
						
						// What's the username to connect?
						$database_user = 'root';
						
						// What's the password for that user?
						$database_password = 'password';
						
						// What's the name of the database?
						$database = 'social';
						
						// User the MySQLi class to connect to database
				        $mysqli = new mysqli($database_host, $database_user, $database_password, $database);
						
						// Query for the available forum boards
						$sql = "SELECT * FROM forum_boards WHERE isDeleted!=1";
						$query = $mysqli->query($sql);
						
						// User fetch_assoc() to get all the rows
						$boards = array();
						while($rows = $query->fetch_assoc()){
							$boards[] = $rows;
						}
						
						// If the form was submitted
						if(!empty($_POST)){
							// Make sure that the values aren't blank
							$title = trim($_POST['title']);
							$content = trim($_POST['content']);
							
							if($title == '' || $content == ''){
								$error = 'You must enter both a title and a thread.';
							}
							else {
								// Post thread and santitize data
                                $title = $mysqli->real_escape_string($title);
                                $content = $mysqli->real_escape_string($content);
								
								// Get the userID from the $_SESSION array
								$userID = $_SESSION['userID'];
								
								// Get the current time according to the server
								$time = time();
								
								// Get the boardID thanks to the select box
								$boardID = $_POST['boardID'];
								
								$sql = "INSERT INTO forum_threads (boardID, userID, title, content, created) VALUES(" . $boardID . ", " . $userID . ", '" . htmlentities($title) . "', '" . htmlentities($content) . "', " . $time . ")";
								$query = $mysqli->query($sql);
								
								// Get the thread's ID number
								$threadID = $mysqli->insert_id;
								
								// Redirect the user to the the thread page with the thread's ID
								header('Location: /forum/thread.php?threadID=' . $threadID);
							}
						}
					?>
					
					<html>
						<head>
							<title>Post a thread</title>
						</head>
						
						<body>
							
							<h1>Post a thread</h1>
							
							<?php
								if(isset($error)){
									echo $error;
								}
							?>
							
							<form action="" method="post">
								<p>
									Which board?
									<br/>
									<select name="boardID">
										<?php foreach($boards as $board): ?>
											<option value="<?php echo $board['boardID']; ?>"><?php echo $board['board']; ?></option>
										<?php endforeach; ?>
									</select>
								</p>
								
								<p>
									Title
									<br/>
									<input type="text" name="title" />
								<p>
								
								<p>
									Thread
									<br/>
									<textarea name="content"></textarea>
								</p>
								
								<p>
									<button type="submit">Post thread</button>
								<p>
							</form>
							
						</body>
					</html>
				
Next, we'll work on viewing a single thread now that we've created one.

Contact us

Questions or problems? Want to contribute to this tutorial or others?

Contact us