π§© Module 12: Final Project β Simple Blog System
Objective: Build a complete, functional Blog System using PHP and MySQL.
Students will be able to create, read, edit, and delete posts, with basic admin authentication and error handling.
π§± Project Overview
Your final project will include:
- A home page that lists all blog posts
- A form to add new posts
- A page to edit and delete posts
- A database to store posts
- Sessions for simple admin login
- Error handling to keep the system stable
π Project Structure
php-blog/
β
βββ db.php
βββ index.php
βββ add-post.php
βββ edit-post.php
βββ delete-post.php
βββ login.php
βββ logout.php
βββ style.css
πΉ Step 1: Set Up Database
Create database:
- Name:
streetgeek_blog
Create table:
CREATE TABLE posts (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
author VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
πΉ Step 2: Database Connection (db.php)
<?php
$host = "localhost";
$user = "root";
$pass = "";
$db = "streetgeek_blog";
$conn = new mysqli($host, $user, $pass, $db);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
?>
πΉ Step 3: Blog Homepage (index.php)
Displays all blog posts in reverse order.
<?php include('db.php'); ?>
<!DOCTYPE html>
<html>
<head>
<title>StreetGeek Blog</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>StreetGeek Blog</h1>
<a href="add-post.php" class="button">+ Add New Post</a>
<hr>
<?php
$sql = "SELECT * FROM posts ORDER BY created_at DESC";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
echo "<h2>" . htmlspecialchars($row['title']) . "</h2>";
echo "<p>" . nl2br(htmlspecialchars(substr($row['content'], 0, 250))) . "...</p>";
echo "<p><em>By " . htmlspecialchars($row['author']) . " on " . $row['created_at'] . "</em></p>";
echo "<a href='edit-post.php?id=" . $row['id'] . "'>Edit</a> | ";
echo "<a href='delete-post.php?id=" . $row['id'] . "'>Delete</a>";
echo "<hr>";
}
} else {
echo "<p>No posts found.</p>";
}
$conn->close();
?>
</body>
</html>
πΉ Step 4: Add New Post (add-post.php)
<?php include('db.php'); ?>
<!DOCTYPE html>
<html>
<head>
<title>Add Post</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h2>Add a New Blog Post</h2>
<form method="POST" action="">
Title: <br>
<input type="text" name="title" required><br>
Content: <br>
<textarea name="content" rows="8" required></textarea><br>
Author: <br>
<input type="text" name="author" required><br>
<input type="submit" name="submit" value="Publish Post">
</form>
<?php
if (isset($_POST['submit'])) {
$title = htmlspecialchars($_POST['title']);
$content = htmlspecialchars($_POST['content']);
$author = htmlspecialchars($_POST['author']);
$stmt = $conn->prepare("INSERT INTO posts (title, content, author) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $title, $content, $author);
if ($stmt->execute()) {
echo "<p style='color:green;'>Post published successfully!</p>";
} else {
echo "<p style='color:red;'>Error: " . $conn->error . "</p>";
}
}
?>
<a href="index.php">β Back to Blog</a>
</body>
</html>
πΉ Step 5: Edit Post (edit-post.php)
<?php include('db.php'); ?>
<?php
if (isset($_GET['id'])) {
$id = intval($_GET['id']);
$result = $conn->query("SELECT * FROM posts WHERE id=$id");
$post = $result->fetch_assoc();
}
if (isset($_POST['update'])) {
$title = htmlspecialchars($_POST['title']);
$content = htmlspecialchars($_POST['content']);
$author = htmlspecialchars($_POST['author']);
$id = intval($_POST['id']);
$stmt = $conn->prepare("UPDATE posts SET title=?, content=?, author=? WHERE id=?");
$stmt->bind_param("sssi", $title, $content, $author, $id);
$stmt->execute();
header("Location: index.php");
exit;
}
?>
<h2>Edit Post</h2>
<form method="POST" action="">
<input type="hidden" name="id" value="<?php echo $post['id']; ?>">
Title: <br>
<input type="text" name="title" value="<?php echo htmlspecialchars($post['title']); ?>" required><br>
Content: <br>
<textarea name="content" rows="8" required><?php echo htmlspecialchars($post['content']); ?></textarea><br>
Author: <br>
<input type="text" name="author" value="<?php echo htmlspecialchars($post['author']); ?>" required><br>
<input type="submit" name="update" value="Update Post">
</form>
<a href="index.php">β Back to Blog</a>
πΉ Step 6: Delete Post (delete-post.php)
<?php include('db.php'); ?>
<?php
if (isset($_GET['id'])) {
$id = intval($_GET['id']);
$stmt = $conn->prepare("DELETE FROM posts WHERE id=?");
$stmt->bind_param("i", $id);
$stmt->execute();
}
header("Location: index.php");
exit;
?>
πΉ Step 7: Admin Login (login.php / logout.php)
Add basic session login to protect editing/deleting.
login.php
<?php
session_start();
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$user = $_POST["username"];
$pass = $_POST["password"];
if ($user == "admin" && $pass == "1234") {
$_SESSION["admin"] = $user;
header("Location: index.php");
exit;
} else {
$error = "Invalid login.";
}
}
?>
<h2>Admin Login</h2>
<form method="POST" action="">
Username: <input type="text" name="username"><br>
Password: <input type="password" name="password"><br>
<input type="submit" value="Login">
</form>
<?php if (isset($error)) echo "<p style='color:red;'>$error</p>"; ?>
logout.php
<?php
session_start();
session_destroy();
header("Location: login.php");
exit;
?>
You can extend your edit/delete files to check:
<?php
session_start();
if (!isset($_SESSION["admin"])) {
header("Location: login.php");
exit;
}
?>
πΉ Step 8: Add Basic Styling (style.css)
body {
font-family: Arial, sans-serif;
margin: 40px;
background: #f5f6fa;
color: #333;
}
h1, h2 {
color: #0E477B;
}
input, textarea {
width: 100%;
margin-bottom: 10px;
padding: 8px;
}
.button {
background: #0E477B;
color: white;
padding: 8px 16px;
text-decoration: none;
border-radius: 4px;
}
.button:hover {
background: #08315c;
}
β Clean, readable UI for your first blog system.
π― BONUS: Error Handling Integration
Add this to the top of db.php:
ini_set('log_errors', 1);
ini_set('error_log', 'blog-errors.log');
error_reporting(E_ALL);
β
Logs database or PHP errors to blog-errors.log safely.
π§Ύ Module 12 Quiz
| # | Question | Options | Correct |
|---|---|---|---|
| 1 | What SQL command retrieves data? | a) GET Β· b) SELECT Β· c) FETCH | b |
| 2 | What function connects PHP to MySQL? | a) mysqli_connect() Β· b) connect_db() Β· c) mysql_start() | a |
| 3 | What does CRUD stand for? | a) Create, Read, Update, Delete Β· b) Copy, Read, Upload, Download | a |
| 4 | How do you prevent SQL injection? | a) Escape quotes Β· b) Use prepared statements Β· c) Use cookies | b |
| 5 | What command deletes a record from a table? | a) DROP Β· b) ERASE Β· c) DELETE | c |
πͺ FINAL CHALLENGE β StreetGeek Simple CMS
Objective: Transform your blog into a lightweight CMS with:
- Secure admin login
- Create/Edit/Delete blog posts
- Error logging
- Dynamic homepage
Bonus Features:
- β Add βPublished Dateβ and βCategoryβ fields
- β Implement search or filter by author
- β Add a βRead Moreβ page for full post content
π§Ύ Submission Checklist
- β
Database:
streetgeek_blogcreated - β
index.phpβ displays posts - β
add-post.phpβ inserts new posts - β
edit-post.phpβ updates existing post - β
delete-post.phpβ removes posts - β
login.php+logout.phpβ working session login - β CSS applied for layout
- β Quiz completed
π CONGRATULATIONS! π
Youβve just built your first dynamic PHP + MySQL application.
You now understand the full lifecycle of a PHP web app β from server setup to database integration and user interaction.
Next steps:
- Deploy your project on your StreetGeek VPS or LocalWP.
- Back up your database using phpMyAdmin.
- Prepare your course capstone submission for review.