Project Overview

A Forum System allows users to engage in discussions by posting topics and replies. This project covers user authentication, topic creation, posting replies, and organizing discussions using PHP and MySQL. It serves as a foundation for building community-driven websites.

Prerequisites

Ensure you have the following:

  • Web Server: Apache (using XAMPP, WAMP, or MAMP)
  • PHP: Version 7.4 or higher
  • MySQL: For database management
  • Code Editor: VS Code, Sublime Text, PHPStorm, etc.
  • Composer: For dependency management (optional)
  • Basic Understanding of User Authentication and Database Relationships

Step-by-Step Procedure

1. Setting Up the Development Environment

  1. Install XAMPP:
    • Download from XAMPP Official Website.
    • Follow the installation wizard and install it in the default directory.
  2. Start Apache and MySQL:
    • Open the XAMPP Control Panel.
    • Start the Apache and MySQL modules.

2. Creating the Database

  1. Access phpMyAdmin:
    • Navigate to http://localhost/phpmyadmin/ in your browser.
  2. Create a New Database:
    • Click on “New” in the left sidebar.
    • Name the database forum_system.
    • Choose “utf8mb4_unicode_ci” as the collation.
    • Click “Create”.
  3. Create users, topics, and replies Tables:
    • users Table: Field Type Null Key Default Extra id INT NO PRI NULL AUTO_INCREMENT username VARCHAR(50) NO UNI NULL email VARCHAR(100) NO UNI NULL password VARCHAR(255) NO NULL created_at TIMESTAMP NO CURRENT_TIMESTAMP
    • topics Table: Field Type Null Key Default Extra id INT NO PRI NULL AUTO_INCREMENT user_id INT NO MUL NULL title VARCHAR(255) NO NULL content TEXT NO NULL created_at TIMESTAMP NO CURRENT_TIMESTAMP
    • replies Table: Field Type Null Key Default Extra id INT NO PRI NULL AUTO_INCREMENT topic_id INT NO MUL NULL user_id INT NO MUL NULL content TEXT NO NULL created_at TIMESTAMP NO CURRENT_TIMESTAMP
    • Click “Save” after creating each table.
  4. Establish Foreign Keys: To maintain referential integrity, set up foreign keys.
    • For topics.user_id:
      • Select the topics table.
      • Go to the “Structure” tab.
      • Click “Relation view” at the bottom.
      • Set user_id to reference users.id with ON DELETE CASCADE.
    • For replies.topic_id:
      • Select the replies table.
      • Go to the “Structure” tab.
      • Click “Relation view”.
      • Set topic_id to reference topics.id with ON DELETE CASCADE.
    • For replies.user_id:
      • Select the replies table.
      • Go to the “Structure” tab.
      • Click “Relation view”.
      • Set user_id to reference users.id with ON DELETE CASCADE.

3. Project Structure

Organize your project files as follows:

forum-system/
├── assets/
│   ├── css/
│   │   └── styles.css
│   └── js/
│       └── scripts.js
├── config/
│   └── db.php
├── templates/
│   ├── header.php
│   └── footer.php
├── register.php
├── login.php
├── logout.php
├── create_topic.php
├── view_topic.php
├── post_reply.php
├── edit_topic.php
├── delete_topic.php
├── edit_reply.php
├── delete_reply.php
├── index.php
└── README.md

4. Configuration

a. Database Connection (config/db.php)

Create a file named db.php inside the config directory to handle database connections.

<?php
// config/db.php

$host = 'localhost';
$db   = 'forum_system';
$user = 'root'; // Default XAMPP MySQL user
$pass = '';     // Default XAMPP MySQL password is empty
$charset = 'utf8mb4';

$dsn = "mysql:host=$host;dbname=$db;charset=$charset";

$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION, // Enable exceptions
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,       // Fetch associative arrays
    PDO::ATTR_EMULATE_PREPARES   => false,                  // Disable emulation
];

try {
    $pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
    // Handle connection errors
    http_response_code(500);
    echo "Database connection failed.";
    exit;
}
?>

5. Creating Reusable Templates

a. Header (templates/header.php)
<?php
// templates/header.php
session_start();
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Forum System</title>
    <link rel="stylesheet" href="/forum-system/assets/css/styles.css">
</head>
<body>
    <header>
        <h1>Forum System</h1>
        <nav>
            <a href="/forum-system/index.php">Home</a>
            <?php if (isset($_SESSION['user_id'])): ?>
                <a href="/forum-system/create_topic.php">Create Topic</a>
                <a href="/forum-system/logout.php">Logout (<?php echo htmlspecialchars($_SESSION['username']); ?>)</a>
            <?php else: ?>
                <a href="/forum-system/login.php">Login</a>
                <a href="/forum-system/register.php">Register</a>
            <?php endif; ?>
        </nav>
    </header>
    <main>
b. Footer (templates/footer.php)
<?php
// templates/footer.php
?>
    </main>
    <footer>
        <p>&copy; <?php echo date("Y"); ?> Your Company Name</p>
    </footer>
    <script src="/forum-system/assets/js/scripts.js"></script>
</body>
</html>

6. Styling the Application (assets/css/styles.css)

Add basic styles to enhance the appearance.

/* assets/css/styles.css */

body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
}

header, footer {
    background-color: #444;
    color: #fff;
    padding: 10px 20px;
}

header h1, footer p {
    margin: 0;
}

nav a {
    color: #fff;
    margin-right: 15px;
    text-decoration: none;
}

main {
    padding: 20px;
}

form {
    max-width: 600px;
    margin: auto;
}

.form-group {
    margin-bottom: 15px;
}

label {
    display: block;
    margin-bottom: 5px;
}

input[type="text"],
input[type="email"],
input[type="password"],
textarea {
    width: 100%;
    padding: 8px;
    box-sizing: border-box;
}

button {
    padding: 10px 15px;
    background-color: #007BFF;
    color: #fff;
    border: none;
    cursor: pointer;
}

button:hover {
    background-color: #0069d9;
}

table {
    width: 100%;
    border-collapse: collapse;
    margin-top: 20px;
}

table, th, td {
    border: 1px solid #ddd;
}

th, td {
    padding: 12px;
    text-align: left;
}

th {
    background-color: #f4f4f4;
}

a {
    color: #007BFF;
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
}

.error {
    background-color: #f8d7da;
    color: #842029;
    padding: 15px;
    margin-bottom: 20px;
    border: 1px solid #f5c2c7;
    border-radius: 4px;
}

.success {
    background-color: #d1e7dd;
    color: #0f5132;
    padding: 15px;
    margin-bottom: 20px;
    border: 1px solid #badbcc;
    border-radius: 4px;
}

.topic-title {
    font-size: 1.2em;
    font-weight: bold;
}

.reply {
    margin-left: 20px;
    border-left: 2px solid #ccc;
    padding-left: 10px;
}

7. User Registration (register.php)

This page allows new users to create an account.

<?php
// register.php

require 'config/db.php';
require 'templates/header.php';

$errors = [];
$success = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Sanitize and validate inputs
    $username = trim($_POST['username']);
    $email    = trim($_POST['email']);
    $password = trim($_POST['password']);
    $confirm_password = trim($_POST['confirm_password']);

    if (empty($username)) {
        $errors[] = 'Username is required.';
    }

    if (empty($email)) {
        $errors[] = 'Email is required.';
    } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors[] = 'Invalid email format.';
    }

    if (empty($password)) {
        $errors[] = 'Password is required.';
    } elseif (strlen($password) < 6) {
        $errors[] = 'Password must be at least 6 characters.';
    }

    if ($password !== $confirm_password) {
        $errors[] = 'Passwords do not match.';
    }

    // Check if username or email already exists
    if (empty($errors)) {
        $stmt = $pdo->prepare('SELECT id FROM users WHERE username = ? OR email = ?');
        $stmt->execute([$username, $email]);
        if ($stmt->fetch()) {
            $errors[] = 'Username or email already exists.';
        }
    }

    if (empty($errors)) {
        // Hash the password
        $hashed_password = password_hash($password, PASSWORD_DEFAULT);

        // Insert into database
        $stmt = $pdo->prepare('INSERT INTO users (username, email, password) VALUES (?, ?, ?)');
        if ($stmt->execute([$username, $email, $hashed_password])) {
            $success = 'Registration successful. You can now <a href="login.php">login</a>.';
            // Clear form fields
            $username = $email = $password = $confirm_password = '';
        } else {
            $errors[] = 'There was an error registering. Please try again.';
        }
    }
}
?>

<h2>Register</h2>

<?php if (!empty($errors)): ?>
    <div class="error">
        <ul>
            <?php foreach($errors as $error): ?>
                <li><?php echo htmlspecialchars($error); ?></li>
            <?php endforeach; ?>
        </ul>
    </div>
<?php endif; ?>

<?php if ($success): ?>
    <div class="success">
        <p><?php echo $success; ?></p>
    </div>
<?php endif; ?>

<form action="register.php" method="POST">
    <div class="form-group">
        <label for="username">Username:</label>
        <input type="text" id="username" name="username" value="<?php echo htmlspecialchars($username ?? ''); ?>" required>
    </div>

    <div class="form-group">
        <label for="email">Email:</label>
        <input type="email" id="email" name="email" value="<?php echo htmlspecialchars($email ?? ''); ?>" required>
    </div>

    <div class="form-group">
        <label for="password">Password (min 6 characters):</label>
        <input type="password" id="password" name="password" required>
    </div>

    <div class="form-group">
        <label for="confirm_password">Confirm Password:</label>
        <input type="password" id="confirm_password" name="confirm_password" required>
    </div>

    <button type="submit">Register</button>
</form>

<?php
require 'templates/footer.php';
?>

8. User Login (login.php)

This page allows existing users to log in.

<?php
// login.php

require 'config/db.php';
require 'templates/header.php';

$errors = [];
$success = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Sanitize and validate inputs
    $username = trim($_POST['username']);
    $password = trim($_POST['password']);

    if (empty($username)) {
        $errors[] = 'Username is required.';
    }

    if (empty($password)) {
        $errors[] = 'Password is required.';
    }

    if (empty($errors)) {
        // Fetch user from database
        $stmt = $pdo->prepare('SELECT id, password FROM users WHERE username = ?');
        $stmt->execute([$username]);
        $user = $stmt->fetch();

        if ($user && password_verify($password, $user['password'])) {
            // Password is correct, start a session
            $_SESSION['user_id'] = $user['id'];
            $_SESSION['username'] = $username;
            // Redirect to home page
            header('Location: index.php');
            exit;
        } else {
            $errors[] = 'Invalid username or password.';
        }
    }
}
?>

<h2>Login</h2>

<?php if (!empty($errors)): ?>
    <div class="error">
        <ul>
            <?php foreach($errors as $error): ?>
                <li><?php echo htmlspecialchars($error); ?></li>
            <?php endforeach; ?>
        </ul>
    </div>
<?php endif; ?>

<?php if ($success): ?>
    <div class="success">
        <p><?php echo htmlspecialchars($success); ?></p>
    </div>
<?php endif; ?>

<form action="login.php" method="POST">
    <div class="form-group">
        <label for="username">Username:</label>
        <input type="text" id="username" name="username" value="<?php echo htmlspecialchars($username ?? ''); ?>" required>
    </div>

    <div class="form-group">
        <label for="password">Password:</label>
        <input type="password" id="password" name="password" required>
    </div>

    <button type="submit">Login</button>
</form>

<?php
require 'templates/footer.php';
?>

9. Creating a New Topic (create_topic.php)

This page allows authenticated users to create new discussion topics.

<?php
// create_topic.php

require 'config/db.php';
require 'templates/header.php';

// Check if user is logged in
if (!isset($_SESSION['user_id'])) {
    header('Location: login.php');
    exit;
}

$errors = [];
$success = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Sanitize and validate inputs
    $title = trim($_POST['title']);
    $content = trim($_POST['content']);

    if (empty($title)) {
        $errors[] = 'Topic title is required.';
    }

    if (empty($content)) {
        $errors[] = 'Topic content is required.';
    }

    if (empty($errors)) {
        // Insert into database
        $stmt = $pdo->prepare('INSERT INTO topics (user_id, title, content) VALUES (?, ?, ?)');
        if ($stmt->execute([$_SESSION['user_id'], $title, $content])) {
            $success = 'Topic created successfully.';
            // Clear form fields
            $title = $content = '';
        } else {
            $errors[] = 'There was an error creating the topic. Please try again.';
        }
    }
}
?>

<h2>Create New Topic</h2>

<?php if (!empty($errors)): ?>
    <div class="error">
        <ul>
            <?php foreach($errors as $error): ?>
                <li><?php echo htmlspecialchars($error); ?></li>
            <?php endforeach; ?>
        </ul>
    </div>
<?php endif; ?>

<?php if ($success): ?>
    <div class="success">
        <p><?php echo htmlspecialchars($success); ?></p>
    </div>
<?php endif; ?>

<form action="create_topic.php" method="POST">
    <div class="form-group">
        <label for="title">Topic Title:</label>
        <input type="text" id="title" name="title" value="<?php echo htmlspecialchars($title ?? ''); ?>" required>
    </div>

    <div class="form-group">
        <label for="content">Topic Content:</label>
        <textarea id="content" name="content" rows="8" required><?php echo htmlspecialchars($content ?? ''); ?></textarea>
    </div>

    <button type="submit">Create Topic</button>
</form>

<?php
require 'templates/footer.php';
?>

10. Viewing a Single Topic and Its Replies (view_topic.php)

This page displays the full details of a topic along with its replies. Authenticated users can post replies.

<?php
// view_topic.php

require 'config/db.php';
require 'templates/header.php';

// Get topic ID from URL
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;

// Fetch topic details
$stmt = $pdo->prepare('SELECT t.*, u.username FROM topics t JOIN users u ON t.user_id = u.id WHERE t.id = ?');
$stmt->execute([$id]);
$topic = $stmt->fetch();

if (!$topic) {
    echo "<p>Topic not found.</p>";
    require 'templates/footer.php';
    exit;
}

// Fetch replies
$stmt = $pdo->prepare('SELECT r.*, u.username FROM replies r JOIN users u ON r.user_id = u.id WHERE r.topic_id = ? ORDER BY r.created_at ASC');
$stmt->execute([$id]);
$replies = $stmt->fetchAll();

$errors = [];
$success = '';

// Handle reply submission
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Check if user is logged in
    if (!isset($_SESSION['user_id'])) {
        $errors[] = 'You must be logged in to post a reply.';
    } else {
        // Sanitize and validate input
        $reply_content = trim($_POST['reply_content']);

        if (empty($reply_content)) {
            $errors[] = 'Reply content is required.';
        }

        if (empty($errors)) {
            // Insert reply into database
            $stmt = $pdo->prepare('INSERT INTO replies (topic_id, user_id, content) VALUES (?, ?, ?)');
            if ($stmt->execute([$id, $_SESSION['user_id'], $reply_content])) {
                $success = 'Reply posted successfully.';
                // Refresh replies
                $stmt = $pdo->prepare('SELECT r.*, u.username FROM replies r JOIN users u ON r.user_id = u.id WHERE r.topic_id = ? ORDER BY r.created_at ASC');
                $stmt->execute([$id]);
                $replies = $stmt->fetchAll();
                // Clear form field
                $reply_content = '';
            } else {
                $errors[] = 'There was an error posting your reply. Please try again.';
            }
        }
    }
}
?>

<h2><?php echo htmlspecialchars($topic['title']); ?></h2>
<p><strong>By:</strong> <?php echo htmlspecialchars($topic['username']); ?> | <strong>Posted on:</strong> <?php echo htmlspecialchars($topic['created_at']); ?></p>
<p><?php echo nl2br(htmlspecialchars($topic['content'])); ?></p>

<hr>

<h3>Replies</h3>

<?php if ($replies): ?>
    <?php foreach ($replies as $reply): ?>
        <div class="reply">
            <p><strong><?php echo htmlspecialchars($reply['username']); ?></strong> | <em><?php echo htmlspecialchars($reply['created_at']); ?></em></p>
            <p><?php echo nl2br(htmlspecialchars($reply['content'])); ?></p>
            <?php if (isset($_SESSION['user_id']) && $_SESSION['user_id'] === $reply['user_id']): ?>
                <a href="edit_reply.php?id=<?php echo $reply['id']; ?>">Edit</a> |
                <a href="delete_reply.php?id=<?php echo $reply['id']; ?>" onclick="return confirm('Are you sure you want to delete this reply?');">Delete</a>
            <?php endif; ?>
        </div>
        <hr>
    <?php endforeach; ?>
<?php else: ?>
    <p>No replies yet. Be the first to reply!</p>
<?php endif; ?>

<?php if (isset($_SESSION['user_id'])): ?>
    <h3>Post a Reply</h3>

    <?php if (!empty($errors)): ?>
        <div class="error">
            <ul>
                <?php foreach($errors as $error): ?>
                    <li><?php echo htmlspecialchars($error); ?></li>
                <?php endforeach; ?>
            </ul>
        </div>
    <?php endif; ?>

    <?php if ($success): ?>
        <div class="success">
            <p><?php echo htmlspecialchars($success); ?></p>
        </div>
    <?php endif; ?>

    <form action="view_topic.php?id=<?php echo $id; ?>" method="POST">
        <div class="form-group">
            <label for="reply_content">Your Reply:</label>
            <textarea id="reply_content" name="reply_content" rows="5" required><?php echo htmlspecialchars($reply_content ?? ''); ?></textarea>
        </div>
        <button type="submit">Post Reply</button>
    </form>
<?php else: ?>
    <p><a href="login.php">Login</a> to post a reply.</p>
<?php endif; ?>

<a href="index.php">Back to All Topics</a>

<?php
require 'templates/footer.php';
?>

11. Posting a Reply (post_reply.php)

Alternatively, you can handle reply submissions in a separate script. However, for simplicity, the above view_topic.php handles both displaying and posting replies.

12. Editing a Topic (edit_topic.php)

This page allows users to edit their own topics.

<?php
// edit_topic.php

require 'config/db.php';
require 'templates/header.php';

$errors = [];
$success = '';

// Get topic ID from URL
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;

// Fetch existing topic
$stmt = $pdo->prepare('SELECT * FROM topics WHERE id = ?');
$stmt->execute([$id]);
$topic = $stmt->fetch();

if (!$topic) {
    echo "<p>Topic not found.</p>";
    require 'templates/footer.php';
    exit;
}

// Check if the logged-in user is the owner of the topic
if (!isset($_SESSION['user_id']) || $_SESSION['user_id'] !== $topic['user_id']) {
    echo "<p>You do not have permission to edit this topic.</p>";
    require 'templates/footer.php';
    exit;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Sanitize and validate inputs
    $title = trim($_POST['title']);
    $content = trim($_POST['content']);

    if (empty($title)) {
        $errors[] = 'Topic title is required.';
    }

    if (empty($content)) {
        $errors[] = 'Topic content is required.';
    }

    if (empty($errors)) {
        // Update in database
        $stmt = $pdo->prepare('UPDATE topics SET title = ?, content = ? WHERE id = ?');
        if ($stmt->execute([$title, $content, $id])) {
            $success = 'Topic updated successfully.';
            // Refresh topic data
            $stmt = $pdo->prepare('SELECT * FROM topics WHERE id = ?');
            $stmt->execute([$id]);
            $topic = $stmt->fetch();
        } else {
            $errors[] = 'There was an error updating the topic. Please try again.';
        }
    }
}
?>

<h2>Edit Topic</h2>

<?php if (!empty($errors)): ?>
    <div class="error">
        <ul>
            <?php foreach($errors as $error): ?>
                <li><?php echo htmlspecialchars($error); ?></li>
            <?php endforeach; ?>
        </ul>
    </div>
<?php endif; ?>

<?php if ($success): ?>
    <div class="success">
        <p><?php echo htmlspecialchars($success); ?></p>
    </div>
<?php endif; ?>

<form action="edit_topic.php?id=<?php echo $id; ?>" method="POST">
    <div class="form-group">
        <label for="title">Topic Title:</label>
        <input type="text" id="title" name="title" value="<?php echo htmlspecialchars($topic['title']); ?>" required>
    </div>

    <div class="form-group">
        <label for="content">Topic Content:</label>
        <textarea id="content" name="content" rows="8" required><?php echo htmlspecialchars($topic['content']); ?></textarea>
    </div>

    <button type="submit">Update Topic</button>
</form>

<?php
require 'templates/footer.php';
?>

13. Deleting a Topic (delete_topic.php)

This script allows users to delete their own topics along with all associated replies.

<?php
// delete_topic.php

require 'config/db.php';

// Get topic ID from URL
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;

// Fetch existing topic
$stmt = $pdo->prepare('SELECT * FROM topics WHERE id = ?');
$stmt->execute([$id]);
$topic = $stmt->fetch();

if (!$topic) {
    echo "<p>Topic not found.</p>";
    exit;
}

// Check if the logged-in user is the owner of the topic
if (!isset($_SESSION['user_id']) || $_SESSION['user_id'] !== $topic['user_id']) {
    echo "<p>You do not have permission to delete this topic.</p>";
    exit;
}

// Delete topic (replies will be deleted automatically due to foreign key with ON DELETE CASCADE)
$stmt = $pdo->prepare('DELETE FROM topics WHERE id = ?');
$stmt->execute([$id]);

// Redirect to home page
header('Location: index.php');
exit;
?>

14. Editing a Reply (edit_reply.php)

This page allows users to edit their own replies.

<?php
// edit_reply.php

require 'config/db.php';
require 'templates/header.php';

$errors = [];
$success = '';

// Get reply ID from URL
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;

// Fetch existing reply
$stmt = $pdo->prepare('SELECT * FROM replies WHERE id = ?');
$stmt->execute([$id]);
$reply = $stmt->fetch();

if (!$reply) {
    echo "<p>Reply not found.</p>";
    require 'templates/footer.php';
    exit;
}

// Check if the logged-in user is the owner of the reply
if (!isset($_SESSION['user_id']) || $_SESSION['user_id'] !== $reply['user_id']) {
    echo "<p>You do not have permission to edit this reply.</p>";
    require 'templates/footer.php';
    exit;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Sanitize and validate input
    $content = trim($_POST['content']);

    if (empty($content)) {
        $errors[] = 'Reply content is required.';
    }

    if (empty($errors)) {
        // Update in database
        $stmt = $pdo->prepare('UPDATE replies SET content = ? WHERE id = ?');
        if ($stmt->execute([$content, $id])) {
            $success = 'Reply updated successfully.';
            // Refresh reply data
            $stmt = $pdo->prepare('SELECT * FROM replies WHERE id = ?');
            $stmt->execute([$id]);
            $reply = $stmt->fetch();
        } else {
            $errors[] = 'There was an error updating the reply. Please try again.';
        }
    }
}
?>

<h2>Edit Reply</h2>

<?php if (!empty($errors)): ?>
    <div class="error">
        <ul>
            <?php foreach($errors as $error): ?>
                <li><?php echo htmlspecialchars($error); ?></li>
            <?php endforeach; ?>
        </ul>
    </div>
<?php endif; ?>

<?php if ($success): ?>
    <div class="success">
        <p><?php echo htmlspecialchars($success); ?></p>
    </div>
<?php endif; ?>

<form action="edit_reply.php?id=<?php echo $id; ?>" method="POST">
    <div class="form-group">
        <label for="content">Reply Content:</label>
        <textarea id="content" name="content" rows="5" required><?php echo htmlspecialchars($reply['content']); ?></textarea>
    </div>

    <button type="submit">Update Reply</button>
</form>

<?php
require 'templates/footer.php';
?>

15. Deleting a Reply (delete_reply.php)

This script allows users to delete their own replies.

<?php
// delete_reply.php

require 'config/db.php';

// Get reply ID from URL
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;

// Fetch existing reply
$stmt = $pdo->prepare('SELECT * FROM replies WHERE id = ?');
$stmt->execute([$id]);
$reply = $stmt->fetch();

if (!$reply) {
    echo "<p>Reply not found.</p>";
    exit;
}

// Check if the logged-in user is the owner of the reply
if (!isset($_SESSION['user_id']) || $_SESSION['user_id'] !== $reply['user_id']) {
    echo "<p>You do not have permission to delete this reply.</p>";
    exit;
}

// Delete reply
$stmt = $pdo->prepare('DELETE FROM replies WHERE id = ?');
$stmt->execute([$id]);

// Redirect back to the topic page
header('Location: view_topic.php?id=' . $reply['topic_id']);
exit;
?>

16. Testing the Application

  1. Access the Registration Page:
    • Navigate to http://localhost/forum-system/register.php.
    • Fill in the registration form and submit.
    • Verify that the user is registered and redirected appropriately.
  2. Access the Login Page:
    • Navigate to http://localhost/forum-system/login.php.
    • Enter the registered credentials and log in.
    • Verify access to the home page.
  3. Create a New Topic:
    • Navigate to http://localhost/forum-system/create_topic.php.
    • Fill in the topic details and submit.
    • Verify that the topic appears on the home page.
  4. View a Topic:
    • Click on a topic title on the home page.
    • Ensure that the full topic details and any existing replies are displayed.
  5. Post a Reply:
    • On the topic page, fill in the reply form and submit.
    • Verify that the reply appears under the topic.
  6. Edit a Topic and Reply:
    • Click on “Edit” next to a topic or reply.
    • Modify the details and submit.
    • Ensure that changes are reflected appropriately.
  7. Delete a Topic and Reply:
    • Click on “Delete” next to a topic or reply.
    • Confirm deletion.
    • Verify that the topic or reply is removed from the list.
  8. Logout:
    • Click on “Logout”.
    • Verify that access to protected pages is restricted.

17. Deployment Considerations

When deploying your Forum System to a live server, consider the following:

  • Implement Comprehensive Authentication:
    • Ensure secure password storage using hashing algorithms.
    • Consider implementing features like email verification and password recovery.
  • Prevent Spam and Abuse:
    • Integrate CAPTCHA in registration and reply forms.
    • Implement rate limiting to prevent excessive postings.
  • Use HTTPS:
    • Secure data transmission by implementing HTTPS.
  • Input Validation and Sanitization:
    • Thoroughly validate and sanitize all user inputs to prevent SQL injection and XSS attacks.
  • User Roles and Permissions:
    • Implement different user roles (e.g., admin, moderator, user) with varying permissions.
  • Error Handling:
    • Provide user-friendly error messages without exposing sensitive information.
  • Regular Backups:
    • Schedule regular backups of your database to prevent data loss.
  • Performance Optimization:
    • Optimize database queries and implement caching strategies for better performance.

18. Enhancements and Best Practices

  • Pagination:
    • Implement pagination for topics and replies to handle large volumes of data.
  • Search Functionality:
    • Allow users to search for topics by keywords or filters.
  • Notifications:
    • Implement email or in-app notifications for new replies or mentions.
  • Responsive Design:
    • Enhance the forum’s responsiveness for better viewing on various devices.
  • API Integration:
    • Expose forum data via a RESTful API for integration with other applications or mobile apps.
  • Moderation Tools:
    • Provide tools for moderators to manage topics and replies effectively.
  • User Profiles:
    • Enhance user profiles with avatars, bios, and activity logs.
Leave a Comment

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *