Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the health-check domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home/yogisv5/sitesbyyogi.com/wp-includes/functions.php on line 6260
MODULE 12: Final Project – Simple Blog System - SitesByYogi

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

# 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_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.