Web Development
HTML Course
CSS Course
JavaScript Course
PHP Course
Python Course
SQL Course
SEO Course

Practical Projects in PHP + SQL

Mini CMS / Blog (Users, Posts, Comments)

A mini CMS or a simple blog is an excellent project to practice PHP & MySQL. Typically, such a project involves the following tables:

Database Structure

Example of creating tables in phpMyAdmin or with a PHP script:

CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(50) NOT NULL,
  email VARCHAR(100) NOT NULL UNIQUE,
  password VARCHAR(255) NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE posts (
  id INT AUTO_INCREMENT PRIMARY KEY,
  user_id INT NOT NULL,
  title VARCHAR(100) NOT NULL,
  content TEXT NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

CREATE TABLE comments (
  id INT AUTO_INCREMENT PRIMARY KEY,
  post_id INT NOT NULL,
  user_id INT NOT NULL,
  content TEXT NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE,
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

Main Features

PHP Code Example - Display Posts and Comments

<?php
try {
    $pdo = new PDO("mysql:host=localhost;dbname=traffice-test", "root", "");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $sql = "SELECT posts.id AS post_id, posts.title, posts.content, posts.created_at,
                   users.name AS author_name, users.email AS author_email
            FROM posts
            INNER JOIN users ON posts.user_id = users.id
            ORDER BY posts.created_at DESC";
    $stmt = $pdo->query($sql);

    while ($post = $stmt->fetch(PDO::FETCH_ASSOC)) {
        echo "<h4>" . htmlspecialchars($post['title']) . "</h4>";
        echo "<p>" . htmlspecialchars($post['content']) . "</p>";
        echo "<small>Written by: " . htmlspecialchars($post['author_name']) . " (" . htmlspecialchars($post['author_email']) . ") on " . $post['created_at'] . "</small><br>";

        // display comments
        $sql_comments = "SELECT comments.content, comments.created_at, users.name AS commenter
                         FROM comments
                         INNER JOIN users ON comments.user_id = users.id
                         WHERE comments.post_id = :post_id
                         ORDER BY comments.created_at ASC";
        $stmt_comments = $pdo->prepare($sql_comments);
        $stmt_comments->execute(['post_id' => $post['post_id']]);
        while ($comment = $stmt_comments->fetch(PDO::FETCH_ASSOC)) {
            echo "<div style='margin-left:20px'>";
            echo "<p>" . htmlspecialchars($comment['commenter']) . ": " . htmlspecialchars($comment['content']) . "</p>";
            echo "<small>" . $comment['created_at'] . "</small></div>";
        }

        echo "<hr>";
    }
} catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
}
?>
๐Ÿ”ง PHP Example: Display Posts and Comments
<?php
try {
$pdo = new PDO("mysql:host=localhost;dbname=traffice-test", "traffice_php", "!@y3Ge-Z!WQI");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $sql = "SELECT posts.id AS post_id, posts.title, posts.content, posts.created_at,
                   users.name AS author_name, users.email AS author_email
            FROM posts
            INNER JOIN users ON posts.user_id = users.id
            ORDER BY posts.created_at DESC";
    $stmt = $pdo->query($sql);

    while ($post = $stmt->fetch(PDO::FETCH_ASSOC)) {
        echo "<h4>" . htmlspecialchars($post['title']) . "</h4>";
        echo "<p>" . htmlspecialchars($post['content']) . "</p>";
        echo "<small>Scris de: " . htmlspecialchars($post['author_name']) . " (" . htmlspecialchars($post['author_email']) . ") la " . $post['created_at'] . "</small><br>";

         $sql_comments = "SELECT comments.content, comments.created_at, users.name AS commenter
                         FROM comments
                         INNER JOIN users ON comments.user_id = users.id
                         WHERE comments.post_id = :post_id
                         ORDER BY comments.created_at ASC";
        $stmt_comments = $pdo->prepare($sql_comments);
        $stmt_comments->execute(['post_id' => $post['post_id']]);
        while ($comment = $stmt_comments->fetch(PDO::FETCH_ASSOC)) {
            echo "<div style='margin-left:20px'>";
            echo "<p>" . htmlspecialchars($comment['commenter']) . ": " . htmlspecialchars($comment['content']) . "</p>";
            echo "<small>" . $comment['created_at'] . "</small></div>";
        }

        echo "<hr>";
    }
} catch (PDOException $e) {
    echo "Eroare: " . $e->getMessage();
}
?>

To-Do List with DB

A To-Do List project is ideal for practicing CRUD operations and sessions in PHP. Each user can have their own task list, which is stored in a MySQL database.

Database Structure

Example table for tasks:

CREATE TABLE todos (
  id INT AUTO_INCREMENT PRIMARY KEY,
  user_id INT NOT NULL,
  task VARCHAR(255) NOT NULL,
  is_done TINYINT(1) DEFAULT 0,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

PHP Example - CRUD for To-Do List

<?php
session_start();
try {
    $pdo = new PDO("mysql:host=localhost;dbname=traffice-test", "root", "");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $user_id = 1; // Example, current user

    // Add task
    if(isset($_POST['add_task'])) {
        $task = $_POST['task'];
        $stmt = $pdo->prepare("INSERT INTO todos (user_id, task) VALUES (:user_id, :task)");
        $stmt->execute(['user_id' => $user_id, 'task' => $task]);
    }

    // Delete task
    if(isset($_GET['delete_id'])) {
        $stmt = $pdo->prepare("DELETE FROM todos WHERE id = :id AND user_id = :user_id");
        $stmt->execute(['id' => $_GET['delete_id'], 'user_id' => $user_id]);
    }

    // Mark as done
    if(isset($_GET['toggle_id'])) {
        $stmt = $pdo->prepare("UPDATE todos SET is_done = 1 - is_done WHERE id = :id AND user_id = :user_id");
        $stmt->execute(['id' => $_GET['toggle_id'], 'user_id' => $user_id]);
    }

    // Retrieve all tasks
    $stmt = $pdo->prepare("SELECT * FROM todos WHERE user_id = :user_id ORDER BY created_at DESC");
    $stmt->execute(['user_id' => $user_id]);
    $todos = $stmt->fetchAll(PDO::FETCH_ASSOC);

} catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
}
?>

<h3>My Task List</h3>
<form method="post">
  <input type="text" name="task" placeholder="Add a task" required>
  <button type="submit" name="add_task">Add</button>
</form>

<ul>
<?php foreach($todos as $todo): ?>
    <li>
        <?= htmlspecialchars($todo['task']) ?>
        <a href="?toggle_id=<?= $todo['id'] ?>">[Toggle]</a>
        <a href="?delete_id=<?= $todo['id'] ?>">[Delete]</a>
        <?php if($todo['is_done']): ?>โœ”<?php endif; ?>
    </li>
<?php endforeach; ?>
</ul>
๐Ÿ”ง PHP Example:
<?php
session_start();
try {
$pdo = new PDO("mysql:host=localhost;dbname=traffice-test", "traffice_php", "!@y3Ge-Z!WQI");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $user_id = 35; // Example: current user

    // Add task
    if(isset($_POST['add_task'])) {
        $task = $_POST['task'];
        $stmt = $pdo->prepare("INSERT INTO todos (user_id, task) VALUES (:user_id, :task)");
        $stmt->execute(['user_id' => $user_id, 'task' => $task]);
    }

    // Delete task
    if(isset($_GET['delete_id'])) {
        $stmt = $pdo->prepare("DELETE FROM todos WHERE id = :id AND user_id = :user_id");
        $stmt->execute(['id' => $_GET['delete_id'], 'user_id' => $user_id]);
    }

    // Toggle task completion
    if(isset($_GET['toggle_id'])) {
        $stmt = $pdo->prepare("UPDATE todos SET is_done = 1 - is_done WHERE id = :id AND user_id = :user_id");
        $stmt->execute(['id' => $_GET['toggle_id'], 'user_id' => $user_id]);
    }

    // Fetch all tasks
    $stmt = $pdo->prepare("SELECT * FROM todos WHERE user_id = :user_id ORDER BY created_at DESC");
    $stmt->execute(['user_id' => $user_id]);
    $todos = $stmt->fetchAll(PDO::FETCH_ASSOC);

} catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
}
?>

<h3>My To-Do List</h3>
<form method="post">
  <input type="text" name="task" placeholder="Add a task" required>
  <button type="submit" name="add_task">Add</button>
</form>

<ul>
<?php foreach($todos as $todo): ?>
    <li>
        <?= htmlspecialchars($todo['task']) ?>
        <a href="?toggle_id=<?= $todo['id'] ?>">[Toggle]</a>
        <a href="?delete_id=<?= $todo['id'] ?>">[Delete]</a>
        <?php if($todo['is_done']): ?>โœ”<?php endif; ?>
    </li>
<?php endforeach; ?>
</ul>

Contact Form with Email Sending

A contact form allows users to send messages directly through the website. The data is validated and then sent using the PHP mail() function.

PHP Example - Simple Contact Form

<?php
$success = '';
$error = '';

if(isset($_POST['send'])) {
    $name = trim($_POST['name']);
    $email = trim($_POST['email']);
    $message = trim($_POST['mesaj']);

    // Simple validation
    if(empty($name) || empty($email) || empty($message)) {
        $error = "All fields are required.";
    } elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $error = "The email address is not valid.";
    } else {
        $to = "contact@example.com"; // recipient address
        $subject = "Message from $name";
        $body = "name: $name\nEmail: $email\n\nMessage:\n$message";
        $headers = "From: $email";

        if(mail($to, $subject, $body, $headers)) {
            $success = "The message has been sent successfully!";
        } else {
            $error = "Error sending the message.";
        }
    }
}
?>

<h3>Contact Form</h3>
<?php if($success): ?>
    <p style="color:green"><?= $success ?></p>
<?php endif; ?>

<?php if($error): ?>
    <p style="color:red"><?= $error ?></p>
<?php endif; ?>

<form method="post">
    <input type="text" name="name" placeholder="your name" required><br>
    <input type="email" name="email" placeholder="your email" required><br>
    <textarea name="mesaj" placeholder="your message" required></textarea><br>
    <button type="submit" name="send">Send</button>
</form>

This code can be placed in a single file and run live. This way, message sending can be tested without additional configuration, using just a local server that supports mail() or by configuring a local SMTP server.

Login / Register with Hashing & Sessions

To create a secure authentication system, we use password_hash() at registration and password_verify() at login. User data is stored in a database (e.g., the users table), and sessions are used to maintain the authentication state.

Update users Table for Login

Add the password column to the users table so we can store the hashed password:

ALTER TABLE users
ADD COLUMN password VARCHAR(255) NOT NULL AFTER email;

PHP version to run from a script and check if the column exists:

<?php
try {
    $pdo = new PDO("mysql:host=localhost;dbname=traffice-test", "root", "");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $sql = "ALTER TABLE users
            ADD COLUMN IF NOT EXISTS password VARCHAR(255) NOT NULL AFTER email";
    $pdo->exec($sql);

    echo "โœ… The 'password' column has been added to the 'users' table.";
} catch (PDOException $e) {
    echo "โŒ Error: " . $e->getMessage();
}
?>

After adding the column, the login and register example will work correctly.

PHP Example - Register

<?php
session_start();
$pdo = new PDO("mysql:host=localhost;dbname=traffice-test","root","");

$register_msg = '';

if(isset($_POST['register'])) {
    $username = trim($_POST['username']);
    $email = trim($_POST['email']);
    $password = $_POST['password'];

    if(empty($username) || empty($email) || empty($password)) {
        $register_msg = "All fields are required.";
    } elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $register_msg = "Invalid email.";
    } else {
        $hash = password_hash($password, PASSWORD_DEFAULT);
        $stmt = $pdo->prepare("INSERT INTO users (name, email, password) VALUES (?, ?, ?)");
        if($stmt->execute([$username, $email, $hash])) {
            $register_msg = "โœ… Account created successfully!";
        } else {
            $register_msg = "โŒ Error creating the account.";
        }
    }
}
?>

<h3>Register Form</h3>
<?php if($register_msg): ?>
    <p><?= $register_msg ?></p>
<?php endif; ?>

<form method="post">
    <input type="text" name="username" placeholder="name" required><br>
    <input type="email" name="email" placeholder="Email" required><br>
    <input type="password" name="password" placeholder="Password" required><br>
    <button type="submit" name="register">Register</button>
</form>

PHP Example - Login

<?php
session_start();
$pdo = new PDO("mysql:host=localhost;dbname=traffice-test","root","");

$login_msg = '';

if(isset($_POST['login'])) {
    $email = trim($_POST['email']);
    $password = $_POST['password'];

    $stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
    $stmt->execute([$email]);
    $user = $stmt->fetch(PDO::FETCH_ASSOC);

    if($user && password_verify($password, $user['password'])) {
        $_SESSION['user_id'] = $user['id'];
        $_SESSION['user_name'] = $user['name'];
        $login_msg = "โœ… Login successful! Welcome, " . htmlspecialchars($user['name']);
    } else {
        $login_msg = "โŒ Incorrect email or password.";
    }
}
?>

<h3>Login Form</h3>
<?php if($login_msg): ?>
    <p><?= $login_msg ?></p>
<?php endif; ?>

<form method="post">
    <input type="email" name="email" placeholder="Email" required><br>
    <input type="password" name="password" placeholder="Password" required><br>
    <button type="submit" name="login">Login</button>
</form>

This code can be placed in a single file to test registration and login live. Sessions allow authentication to persist between pages and secure access to protected areas.

๐Ÿ”ง PHP Example: Register
<?php
session_start();
$pdo = new PDO("mysql:host=localhost;dbname=traffice-test", "traffice_php", "!@y3Ge-Z!WQI");

$register_msg = '';

if(isset($_POST['register'])) {
    $username = trim($_POST['username']);
    $email = trim($_POST['email']);
    $password = $_POST['password'];

    if(empty($username) || empty($email) || empty($password)) {
        $register_msg = "All fields are required.";
    } elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $register_msg = "Invalid email.";
    } else {
        $hash = password_hash($password, PASSWORD_DEFAULT);
        $stmt = $pdo->prepare("INSERT INTO users (name, email, password) VALUES (?, ?, ?)");
        if($stmt->execute([$username, $email, $hash])) {
            $register_msg = "โœ… Account created successfully!";
        } else {
            $register_msg = "โŒ Error creating account.";
        }
    }
}
?>

<h3>Register Form</h3>
<?php if($register_msg): ?>
    <p><?= $register_msg ?></p>
<?php endif; ?>

<form method="post">
    <input type="text" name="username" placeholder="Name" required><br>
    <input type="email" name="email" placeholder="Email" required><br>
    <input type="password" name="password" placeholder="Password" required><br>
    <button type="submit" name="register">Register</button>
</form>
๐Ÿ”ง PHP Example: Login
<?php
session_start();
$pdo = new PDO("mysql:host=localhost;dbname=traffice-test", "traffice_php", "!@y3Ge-Z!WQI");

$login_msg = '';

if(isset($_POST['login'])) {
    $email = trim($_POST['email']);
    $password = $_POST['password'];

    $stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
    $stmt->execute([$email]);
    $user = $stmt->fetch(PDO::FETCH_ASSOC);

    if($user && password_verify($password, $user['password'])) {
        $_SESSION['user_id'] = $user['id'];
        $_SESSION['user_name'] = $user['name'];
        $login_msg = "โœ… Login successful! Welcome, " . htmlspecialchars($user['name']);
    } else {
        $login_msg = "โŒ Incorrect email or password.";
    }
}
?>

<h3>Login Form</h3>
<?php if($login_msg): ?>
    <p><?= $login_msg ?></p>
<?php endif; ?>

<form method="post">
    <input type="email" name="email" placeholder="Email" required><br>
    <input type="password" name="password" placeholder="Password" required><br>
    <button type="submit" name="login">Login</button>
</form>

Flash Messages in PHP

Flash messages are temporary messages that appear only once after an action (e.g., successful login, form error) and disappear after the page reloads. They are usually stored in the session.

Practical Example: Flash message after login

<?php
session_start();

// Set flash message after login
$_SESSION['flash_message'] = "โœ… You have successfully logged in!";

// Redirect to the main page
header("Location: index.php");
exit;
?>
<?php
session_start();

// Display flash message and remove it after displaying
if(isset($_SESSION['flash_message'])) {
    echo "<div class='flash'>" . $_SESSION['flash_message'] . "</div>";
    unset($_SESSION['flash_message']);
}
?>

This way, the message will be visible only once, then it disappears automatically.

Like / Dislike Posts

To implement the like/dislike functionality, we need an additional table to store users' actions on posts.

Preparing the database for examples

1. Create a file named update-db.php in your PHP project folder.

2. Copy the code below into it (the one that creates the traffice-test database, users, posts, post_likes tables, and adds test data).

3. Open your browser and run the file like this:

http://localhost/your-folder-name/update-db.php

4. If everything is fine, you will see the message:

โœ… Database and tables have been created with functional test data.

5. Now you have all tables and data ready to run examples of: CRUD, Flash messages, and Like/Dislike posts.

<?php
try {
    $pdo = new PDO("mysql:host=localhost", "root", "");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // Create database
    $pdo->exec("CREATE DATABASE IF NOT EXISTS traffice-test CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
    $pdo->exec("USE traffice-test");

    // Create users table
    $pdo->exec("CREATE TABLE IF NOT EXISTS users (
        id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(50) NOT NULL,
        email VARCHAR(100) NOT NULL,
        password VARCHAR(255) DEFAULT NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )");

    // Insert users
    $pdo->exec("INSERT INTO users (id, name, email, password) VALUES
        (1, 'John Smith', 'ion.popescu@example.com', '123'),
        (2, 'Mary Ionella', 'maria.ionescu@example.com', '123')
        ON DUPLICATE KEY UPDATE name=VALUES(name), email=VALUES(email)");

    // Create posts table
    $pdo->exec("CREATE TABLE IF NOT EXISTS posts (
        id INT AUTO_INCREMENT PRIMARY KEY,
        user_id INT NOT NULL,
        title VARCHAR(100) NOT NULL,
        content TEXT NOT NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
    )");

    // Insert posts
    $pdo->exec("INSERT INTO posts (id, user_id, title, content) VALUES
        (1, 1, 'First post', 'This is the first post written by user 1.'),
        (2, 1, 'Second post', 'User 1 has another post.'),
        (3, 2, 'Hello!', 'Message written by user 2.')
        ON DUPLICATE KEY UPDATE title=VALUES(title), content=VALUES(content)");

    // Create post_likes table
    $pdo->exec("CREATE TABLE IF NOT EXISTS post_likes (
        id INT AUTO_INCREMENT PRIMARY KEY,
        post_id INT NOT NULL,
        user_id INT NOT NULL,
        type ENUM('like','dislike') NOT NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        UNIQUE KEY unique_like (post_id,user_id),
        FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE,
        FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
    )");

    echo "โœ… Database and tables have been created with functional test data.";

} catch (PDOException $e) {
    echo "โŒ Error: " . $e->getMessage();
}
?>

PHP Example for Like/Dislike

<?php
session_start();
$pdo = new PDO("mysql:host=localhost;dbname=traffice-test", "root", "");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$post_id = 1; // Post ID
$user_id = 1; // User ID
$type = 'like'; // or 'dislike'

// Insert like/dislike
$stmt = $pdo->prepare("INSERT INTO post_likes (post_id, user_id, type) VALUES (?, ?, ?)
                          ON DUPLICATE KEY UPDATE type = VALUES(type)");
$stmt->execute([$post_id, $user_id, $type]);

// Total count of likes and dislikes for a post
$counts = $pdo->query("SELECT type, COUNT(*) as total FROM post_likes WHERE post_id = $post_id GROUP BY type")
              ->fetchAll(PDO::FETCH_ASSOC);

foreach($counts as $c) {
    echo "<p>" . ucfirst($c['type']) . ": " . $c['total'] . "</p>";
}
?>

This way, users can like or dislike, and the total count updates automatically. The `ON DUPLICATE KEY UPDATE` function ensures that a user cannot like and dislike the same post simultaneously.

๐Ÿ”ง PHP Example: like or dislike
<?php
// Database connection
try {
$pdo = new PDO("mysql:host=localhost;dbname=traffice-test", "traffice_php", "!@y3Ge-Z!WQI");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die("DB connection error: " . $e->getMessage());
}

// Process like/dislike
if (isset($_POST['like']) && isset($_POST['post_id']) && isset($_POST['user_id'])) {
    $type = $_POST['like'] === 'like' ? 'like' : 'dislike';
    $stmt = $pdo->prepare("INSERT INTO post_likes (post_id, user_id, type) 
                           VALUES (?, ?, ?)
                           ON DUPLICATE KEY UPDATE type = VALUES(type)");
    $stmt->execute([$_POST['post_id'], $_POST['user_id'], $type]);
}

// Fetch posts and like/dislike count
$sql = "SELECT posts.id, posts.title, posts.content, posts.created_at, users.name, users.email,
               SUM(post_likes.type='like') AS likes,
               SUM(post_likes.type='dislike') AS dislikes
        FROM posts
        INNER JOIN users ON posts.user_id = users.id
        LEFT JOIN post_likes ON posts.id = post_likes.post_id
        GROUP BY posts.id
        ORDER BY posts.created_at DESC";

$stmt = $pdo->query($sql);
$posts = $stmt->fetchAll(PDO::FETCH_ASSOC);

// List of users (for demo: user_id select)
$users = $pdo->query("SELECT * FROM users")->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Like/Dislike Demo</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 800px; margin: auto; }
        .post { border: 1px solid #ccc; padding: 1rem; margin-bottom: 1rem; border-radius: 8px; }
        .buttons { margin-top: 0.5rem; }
        button { margin-right: 0.5rem; }
        select { margin-bottom: 1rem; }
    </style>
</head>
<body>
<h1>Demo: Like / Dislike Posts</h1>

<form method="post">
    <label for="user_id">Select user:</label>
    <select name="user_id" id="user_id">
        <?php foreach($users as $user): ?>
            <option value="<?php echo $user['id']; ?>"><?php echo htmlspecialchars($user['name']); ?></option>
        <?php endforeach; ?>
    </select>
</form>

<?php foreach($posts as $post): ?>
    <div class="post">
        <h2><?php echo htmlspecialchars($post['title']); ?></h2>
        <p><?php echo htmlspecialchars($post['content']); ?></p>
        <small>Written by <?php echo htmlspecialchars($post['name']); ?> (<?php echo htmlspecialchars($post['email']); ?>) on <?php echo $post['created_at']; ?></small>
        <div class="buttons">
            <form method="post" style="display:inline;">
                <input type="hidden" name="post_id" value="<?php echo $post['id']; ?>">
                <input type="hidden" name="user_id" value="<?php echo $users[0]['id']; ?>">
                <button type="submit" name="like" value="like">๐Ÿ‘ Like (<?php echo $post['likes'] ?? 0; ?>)</button>
            </form>
            <form method="post" style="display:inline;">
                <input type="hidden" name="post_id" value="<?php echo $post['id']; ?>">
                <input type="hidden" name="user_id" value="<?php echo $users[0]['id']; ?>">
                <button type="submit" name="like" value="dislike">๐Ÿ‘Ž Dislike (<?php echo $post['dislikes'] ?? 0; ?>)</button>
            </form>
        </div>
    </div>
<?php endforeach; ?>
</body>
</html>
Top