Make your own blog
All posts page
The next step is to add an All Posts screen for administrative users. We'll start with a static mock-up with hard-wired post values:
 
		 
	- assets/main.css assets/main.css
- list-posts.php list-posts.php
- templates/top-menu.php templates/top-menu.php
 
				98
					99
					100
					101
						/* Some browsers make labels too tall, and as a result they incorrectly stack horizontally.
							Let's reset each to the left-hand side to be sure. */
						clear: left;
					}
					98
					99
					100
					101
					102
					103
					104
					105
					106
					107
					108
					109
					110
					111
					112
					113
					114
						/* Some browsers make labels too tall, and as a result they incorrectly stack horizontally.
							Let's reset each to the left-hand side to be sure. */
						clear: left;
					}
					#post-list {
						border-collapse: collapse;
						border: 1px solid silver;
					}
					#post-list td {
						padding: 8px;
					}
					#post-list tbody tr:nth-child(odd) {
						background-color: #f4f4f4;
					}
					1
					2
					3
					4
					5
					6
					7
					8
					9
					10
					11
					12
					13
					14
					15
					16
					17
					18
					19
					20
					21
					22
					23
					24
					25
					26
					27
					28
					29
					30
					31
					32
					33
					34
					35
					36
					37
					38
					39
					40
					41
					42
					43
					44
					45
					46
					47
					48
					49
					50
					51
					52
					53
					54
					55
					56
					57
					58
					59
					60
					61
					62
					63
					64
					<?php
					require_once 'lib/common.php';
					session_start();
					?>
					<!DOCTYPE html>
					<html>
						<head>
							<title>A blog application | Blog posts</title>
							<?php require 'templates/head.php' ?>
						</head>
						<body>
							<?php require 'templates/top-menu.php' ?>
							<h1>Post list</h1>
							<form method="post">
								<table id="post-list">
									<tbody>
										<tr>
											<td>Title of the first post</td>
											<td>
												<a href="edit-post.php?post_id=1">Edit</a>
											</td>
											<td>
												<input
													type="submit"
													name="post[1]"
													value="Delete"
												/>
											</td>
										</tr>
										<tr>
											<td>Title of the second post</td>
											<td>
												<a href="edit-post.php?post_id=2">Edit</a>
											</td>
											<td>
												<input
													type="submit"
													name="post[2]"
													value="Delete"
												/>
											</td>
										</tr>
										<tr>
											<td>Title of the third post</td>
											<td>
												<a href="edit-post.php?post_id=3">Edit</a>
											</td>
											<td>
												<input
													type="submit"
													name="post[3]"
													value="Delete"
												/>
											</td>
										</tr>
									</tbody>
								</table>
							</form>
						</body>
					</html>
					1
					2
					3
					 
					 
					4
					5
					6
					<div class="top-menu">
						<div class="menu-options">
							<?php if (isLoggedIn()): ?>
								<a href="edit-post.php">New post</a>
								|
								Hello <?php echo htmlEscape(getAuthUser()) ?>.
					1
					2
					3
					4
					5
					6
					7
					8
					<div class="top-menu">
						<div class="menu-options">
							<?php if (isLoggedIn()): ?>
								<a href="list-posts.php">All posts</a>
								|
								<a href="edit-post.php">New post</a>
								|
								Hello <?php echo htmlEscape(getAuthUser()) ?>.
					Of course, since this is a restricted screen, we must only allow authorised users to see it. To do so, we redirect back to the home page, and exit as usual:
 
		 
	- list-posts.php list-posts.php
 
				3
					4
					5
					 
					 
					 
					 
					 
					 
					6
					7
					8
					session_start();
					?>
					<!DOCTYPE html>
					<html>
					3
					4
					5
					6
					7
					8
					9
					10
					11
					12
					13
					14
					session_start();
					// Don't let non-auth users see this screen
					if (!isLoggedIn())
					{
						redirectAndExit('index.php');
					}
					?>
					<!DOCTYPE html>
					<html>
					Great stuff. Don't forget to test it by logging out, and then trying to visit the page manually!
What do square brackets in form elements do?
Aha! Glad you asked. First, let's consider this simple form element:
<input type="submit" name="save" value="Save" />This is pretty simple. If the button is pressed, the form is submitted, and the submitted key
savegets the value of the button, "Save".However, consider the scenario where we need several submit buttons carrying out a similar purpose, e.g. a delete button per database row. One solution is to add in the primary key as part of the name:
<input type="submit" name="delete_1" value="Delete" /> <input type="submit" name="delete_2" value="Delete" /> <input type="submit" name="delete_3" value="Delete" />When this form gets submitted, we can search for keys matching this naming specific pattern, and delete the matching row as appropriate. However, this is rather fiddly, so PHP provides a cleaner solution - the square bracket syntax:
<input type="submit" name="delete[1]" value="Delete" /> <input type="submit" name="delete[2]" value="Delete" /> <input type="submit" name="delete[3]" value="Delete" />This helps up cheat by doing some of our parsing for us. Here's what happens in that form if we press the second Delete button:
Array ( [delete] => Array ( [2] => Delete ) )This makes things nice and easy: we just look up the name of the element (i.e.
delete), and then grab the first key value.
Now, the logic we use to read the posts for the front page will be useful also for this new screen. Since we don't want to write this twice, let's move it to a function so we can reuse it later on.
 
		 
	- index.php index.php
- lib/common.php lib/common.php
 
				5
					6
					7
					8
					9
					10
					11
					12
					13
					14
					15
					16
					17
					18
					19
					20
					21
					22
					26
					27
					28
					29
					30
					31
					32
					51
					52
					53
					54
					55
					56
					57
					// Connect to the database, run a query, handle errors
					$pdo = getPDO();
					$stmt = $pdo->query(
						'SELECT
							id, title, created_at, body
						FROM
							post
						ORDER BY
							created_at DESC'
					);
					if ($stmt === false)
					{
						throw new Exception('There was a problem running this query');
					}
					$notFound = isset($_GET['not-found']);
							<?php endif ?>
							<div class="post-list">
								<?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?>
									<div class="post-synopsis">
										<h2>
											<?php echo htmlEscape($row['title']) ?>
											<?php endif ?>
										</div>
									</div>
								<?php endwhile ?>
							</div>
						</body>
					5
					6
					7
					8
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					9
					10
					11
					26
					27
					28
					29
					30
					31
					32
					51
					52
					53
					54
					55
					56
					57
					// Connect to the database, run a query, handle errors
					$pdo = getPDO();
					$posts = getAllPosts($pdo);
					$notFound = isset($_GET['not-found']);
							<?php endif ?>
							<div class="post-list">
								<?php foreach ($posts as $row): ?>
									<div class="post-synopsis">
										<h2>
											<?php echo htmlEscape($row['title']) ?>
											<?php endif ?>
										</div>
									</div>
								<?php endforeach ?>
							</div>
						</body>
					73
					74
					75
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					76
					77
					78
						return date('Y-m-d H:i:s');
					}
					/**
					 * Converts unsafe text to safe, paragraphed, HTML
					 *
					73
					74
					75
					76
					77
					78
					79
					80
					81
					82
					83
					84
					85
					86
					87
					88
					89
					90
					91
					92
					93
					94
					95
					96
					97
					98
					99
					100
					101
					102
						return date('Y-m-d H:i:s');
					}
					/**
					 * Gets a list of posts in reverse order
					 *
					 * @param PDO $pdo
					 * @return array
					 */
					function getAllPosts(PDO $pdo)
					{
						$stmt = $pdo->query(
							'SELECT
								id, title, created_at, body
							FROM
								post
							ORDER BY
								created_at DESC'
						);
						if ($stmt === false)
						{
							throw new Exception('There was a problem running this query');
						}
						return $stmt->fetchAll(PDO::FETCH_ASSOC);
					}
					/**
					 * Converts unsafe text to safe, paragraphed, HTML
					 *
					
	While working on the home page, I noticed I'd used the variable name $row. This
	is rather generic — most things read from a database are rows — so I swapped to
	a better name for it. This is more readable, and fits in with the common naming convention
	of using a plural name for an array and the corresponding singular name for each item.
 
		 
	- index.php index.php
 
				26
					27
					28
					29
					30
					31
					32
					33
					34
					35
					36
					37
					38
					39
					40
					41
					42
					43
					44
					45
					46
					47
					48
					49
					50
					51
					52
							<?php endif ?>
							<div class="post-list">
								<?php foreach ($posts as $row): ?>
									<div class="post-synopsis">
										<h2>
											<?php echo htmlEscape($row['title']) ?>
										</h2>
										<div class="meta">
											<?php echo convertSqlDate($row['created_at']) ?>
											(<?php echo countCommentsForPost($pdo, $row['id']) ?> comments)
										</div>
										<p>
											<?php echo htmlEscape($row['body']) ?>
										</p>
										<div class="post-controls">
											<a
												href="view-post.php?post_id=<?php echo $row['id'] ?>"
											>Read more...</a>
											<?php if (isLoggedIn()): ?>
												|
												<a
													href="edit-post.php?post_id=<?php echo $row['id'] ?>"
												>Edit</a>
											<?php endif ?>
										</div>
					26
					27
					28
					29
					30
					31
					32
					33
					34
					35
					36
					37
					38
					39
					40
					41
					42
					43
					44
					45
					46
					47
					48
					49
					50
					51
					52
							<?php endif ?>
							<div class="post-list">
								<?php foreach ($posts as $post): ?>
									<div class="post-synopsis">
										<h2>
											<?php echo htmlEscape($post['title']) ?>
										</h2>
										<div class="meta">
											<?php echo convertSqlDate($post['created_at']) ?>
											(<?php echo countCommentsForPost($pdo, $post['id']) ?> comments)
										</div>
										<p>
											<?php echo htmlEscape($post['body']) ?>
										</p>
										<div class="post-controls">
											<a
												href="view-post.php?post_id=<?php echo $post['id'] ?>"
											>Read more...</a>
											<?php if (isLoggedIn()): ?>
												|
												<a
													href="edit-post.php?post_id=<?php echo $post['id'] ?>"
												>Edit</a>
											<?php endif ?>
										</div>
					Next, we'll modify the mock-up by adding in a creation time for posts:
 
		 
	- list-posts.php list-posts.php
 
				26
					27
					28
					 
					 
					 
					29
					30
					31
					42
					43
					44
					 
					 
					 
					45
					46
					47
					58
					59
					60
					 
					 
					 
					61
					62
					63
									<tbody>
										<tr>
											<td>Title of the first post</td>
											<td>
												<a href="edit-post.php?post_id=1">Edit</a>
											</td>
										</tr>
										<tr>
											<td>Title of the second post</td>
											<td>
												<a href="edit-post.php?post_id=2">Edit</a>
											</td>
										</tr>
										<tr>
											<td>Title of the third post</td>
											<td>
												<a href="edit-post.php?post_id=3">Edit</a>
											</td>
					26
					27
					28
					29
					30
					31
					32
					33
					34
					42
					43
					44
					45
					46
					47
					48
					49
					50
					58
					59
					60
					61
					62
					63
					64
					65
					66
									<tbody>
										<tr>
											<td>Title of the first post</td>
											<td>
												dd MM YYYY h:mi
											</td>
											<td>
												<a href="edit-post.php?post_id=1">Edit</a>
											</td>
										</tr>
										<tr>
											<td>Title of the second post</td>
											<td>
												dd MM YYYY h:mi
											</td>
											<td>
												<a href="edit-post.php?post_id=2">Edit</a>
											</td>
										</tr>
										<tr>
											<td>Title of the third post</td>
											<td>
												dd MM YYYY h:mi
											</td>
											<td>
												<a href="edit-post.php?post_id=3">Edit</a>
											</td>
					As with our mock-up approach before, once a layout contains everything required, it is time to convert to a working version. So, let's do that now: we'll add a loop and render table data in the HTML.
 
		 
	- list-posts.php list-posts.php
 
				9
					10
					11
					 
					 
					 
					 
					12
					13
					14
					28
					29
					30
					31
					32
					33
					34
					35
					36
					37
					38
					39
					40
					41
					42
					43
					44
					45
					46
					47
					48
					49
					50
					51
					52
					53
					54
					55
					56
					57
					58
					59
					60
					61
					62
					63
					64
					65
					66
					67
					68
					69
					70
					71
					72
					73
					74
					75
					76
					77
					78
					79
					80
					81
						redirectAndExit('index.php');
					}
					?>
					<!DOCTYPE html>
					<html>
							<form method="post">
								<table id="post-list">
									<tbody>
										<tr>
											<td>Title of the first post</td>
											<td>
												dd MM YYYY h:mi
											</td>
											<td>
												<a href="edit-post.php?post_id=1">Edit</a>
											</td>
											<td>
												<input
													type="submit"
													name="post[1]"
													value="Delete"
												/>
											</td>
										</tr>
										<tr>
											<td>Title of the second post</td>
											<td>
												dd MM YYYY h:mi
											</td>
											<td>
												<a href="edit-post.php?post_id=2">Edit</a>
											</td>
											<td>
												<input
													type="submit"
													name="post[2]"
													value="Delete"
												/>
											</td>
										</tr>
										<tr>
											<td>Title of the third post</td>
											<td>
												dd MM YYYY h:mi
											</td>
											<td>
												<a href="edit-post.php?post_id=3">Edit</a>
											</td>
											<td>
												<input
													type="submit"
													name="post[3]"
													value="Delete"
												/>
											</td>
										</tr>
									</tbody>
								</table>
							</form>
					9
					10
					11
					12
					13
					14
					15
					16
					17
					18
					28
					29
					30
					31
					32
					33
					34
					35
					36
					37
					38
					39
					40
					41
					42
					43
					44
					45
					46
					47
					48
					49
					50
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					51
					52
					53
						redirectAndExit('index.php');
					}
					// Connect to the database, run a query
					$pdo = getPDO();
					$posts = getAllPosts($pdo);
					?>
					<!DOCTYPE html>
					<html>
							<form method="post">
								<table id="post-list">
									<tbody>
										<?php foreach ($posts as $post): ?>
											<tr>
												<td>
													<?php echo htmlEscape($post['title']) ?>
												</td>
												<td>
													<?php echo convertSqlDate($post['created_at']) ?>
												</td>
												<td>
													<a href="edit-post.php?post_id=<?php echo $post['id']?>">Edit</a>
												</td>
												<td>
													<input
														type="submit"
														name="delete-post[<?php echo $post['id']?>]"
														value="Delete"
													/>
												</td>
											</tr>
										<?php endforeach ?>
									</tbody>
								</table>
							</form>
					As it stands, the user may click on a delete button to remove a post, but this is not presently handled. So, let's do that now:
 
		 
	- lib/list-posts.php lib/list-posts.php
- list-posts.php list-posts.php
 
				1
					2
					3
					4
					5
					6
					7
					8
					9
					10
					11
					12
					13
					14
					15
					16
					17
					18
					19
					20
					21
					22
					23
					24
					25
					26
					27
					28
					29
					30
					<?php
					/**
					 * Tries to delete the specified post
					 *
					 * @param PDO $pdo
					 * @param integer $postId
					 * @return boolean Returns true on successful deletion
					 * @throws Exception
					 */
					function deletePost(PDO $pdo, $postId)
					{
						$sql = "
							DELETE FROM
								post
							WHERE
								id = :id
						";
						$stmt = $pdo->prepare($sql);
						if ($stmt === false)
						{
							throw new Exception('There was a problem preparing this query');
						}
						$result = $stmt->execute(
							array('id' => $postId, )
						);
						return $result !== false;
					}
					1
					2
					 
					3
					4
					5
					10
					11
					12
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					 
					13
					14
					15
					<?php
					require_once 'lib/common.php';
					session_start();
						redirectAndExit('index.php');
					}
					// Connect to the database, run a query
					$pdo = getPDO();
					$posts = getAllPosts($pdo);
					1
					2
					3
					4
					5
					6
					10
					11
					12
					13
					14
					15
					16
					17
					18
					19
					20
					21
					22
					23
					24
					25
					26
					27
					28
					29
					30
					<?php
					require_once 'lib/common.php';
					require_once 'lib/list-posts.php';
					session_start();
						redirectAndExit('index.php');
					}
					if ($_POST)
					{
						$deleteResponse = $_POST['delete-post'];
						if ($deleteResponse)
						{
							$keys = array_keys($deleteResponse);
							$deletePostId = $keys[0];
							if ($deletePostId)
							{
								deletePost(getPDO(), $deletePostId);
								redirectAndExit('list-posts.php');
							}
						}
					}
					// Connect to the database, run a query
					$pdo = getPDO();
					$posts = getAllPosts($pdo);
					Finally let's add in a post count on this page:
 
		 
	- list-posts.php list-posts.php
 
				41
					42
					43
					 
					 
					44
					45
					46
							<h1>Post list</h1>
							<form method="post">
								<table id="post-list">
									<tbody>
					41
					42
					43
					44
					45
					46
					47
					48
							<h1>Post list</h1>
							<p>You have <?php echo count($posts) ?> posts.
							<form method="post">
								<table id="post-list">
									<tbody>
					 Download
						Download