StreetGeek Academy Β· PHP Foundations

🧩 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

#QuestionOptionsCorrect
1What SQL command retrieves data?a) GET Β· b) SELECT Β· c) FETCHb
2What function connects PHP to MySQL?a) mysqli_connect() Β· b) connect_db() Β· c) mysql_start()a
3What does CRUD stand for?a) Create, Read, Update, Delete Β· b) Copy, Read, Upload, Downloada
4How do you prevent SQL injection?a) Escape quotes Β· b) Use prepared statements Β· c) Use cookiesb
5What command deletes a record from a table?a) DROP Β· b) ERASE Β· c) DELETEc

πŸ’ͺ 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_blog created
  • βœ… 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.