Curs Web Development
Curs HTML
Curs CSS
Curs Javascript
Curs PHP
Curs Phyton
Curs SQL
Curs SEO

Proiecte practice în PHP + SQL

Mini CMS / Blog (Users, Posts, Comments)

Un mini CMS sau un blog simplu este un proiect excelent pentru a exersa PHP & MySQL. De obicei, un astfel de proiect implică următoarele tabele:

Structura bazei de date

Exemplu de creare a tabelelor în phpMyAdmin sau cu script PHP:

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
);

Funcționalități principale

Exemplu cod PHP - afișare postări și comentarii

<?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>Scris de: " . htmlspecialchars($post['author_name']) . " (" . htmlspecialchars($post['author_email']) . ") la " . $post['created_at'] . "</small><br>";

        // afișare comentarii
        $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();
}
?>
🔧 Exemplu PHP: afișare postări și comentarii
<?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>";

        // afișare comentarii
        $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 cu DB

Un proiect de tip To-Do List este ideal pentru a exersa CRUD și sesiuni în PHP. Fiecare utilizator poate avea propria listă de sarcini, iar acestea se stochează într-o bază de date MySQL.

Structura bazei de date

Exemplu de tabel pentru sarcini:

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
);

Exemplu PHP - CRUD pentru 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; // Exemplu, utilizatorul curent

    // Adăugare 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]);
    }

    // Ștergere 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]);
    }

    // Marcarea ca făcut
    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]);
    }

    // Preluare toate task-urile
    $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 "Eroare: " . $e->getMessage();
}
?>

<h3>Lista mea de task-uri</h3>
<form method="post">
  <input type="text" name="task" placeholder="Adaugă un task" required>
  <button type="submit" name="add_task">Adaugă</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'] ?>">[Șterge]</a>
        <?php if($todo['is_done']): ?>✔<?php endif; ?>
    </li>
<?php endforeach; ?>
</ul>
🔧 Exemplu PHP:
<?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 = 1; // Exemplu, utilizatorul curent

    // Adăugare 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]);
    }

    // Ștergere 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]);
    }

    // Marcarea ca făcut
    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]);
    }

    // Preluare toate task-urile
    $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 "Eroare: " . $e->getMessage();
}
?>

<h3>Lista mea de task-uri</h3>
<form method="post">
  <input type="text" name="task" placeholder="Adaugă un task" required>
  <button type="submit" name="add_task">Adaugă</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'] ?>">[Șterge]</a>
        <?php if($todo['is_done']): ?>✔<?php endif; ?>
    </li>
<?php endforeach; ?>
</ul>

Formular de contact cu trimitere pe e-mail

Un formular de contact permite utilizatorilor să trimită mesaje direct prin site. Datele sunt validate și apoi trimise prin funcția PHP mail().

Exemplu PHP - Formular de contact simplu

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

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

    // Validare simplă
    if(empty($nume) || empty($email) || empty($mesaj)) {
        $error = "Toate câmpurile sunt obligatorii.";
    } elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $error = "Adresa de email nu este validă.";
    } else {
        $to = "contact@example.com"; // adresa destinatar
        $subject = "Mesaj de la $nume";
        $body = "Nume: $nume\nEmail: $email\n\nMesaj:\n$mesaj";
        $headers = "From: $email";

        if(mail($to, $subject, $body, $headers)) {
            $success = "Mesajul a fost trimis cu succes!";
        } else {
            $error = "Eroare la trimiterea mesajului.";
        }
    }
}
?>

<h3>Formular de contact</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="nume" placeholder="Numele tău" required><br>
    <input type="email" name="email" placeholder="Email-ul tău" required><br>
    <textarea name="mesaj" placeholder="Mesajul tău" required></textarea><br>
    <button type="submit" name="send">Trimite</button>
</form>

Acest cod poate fi pus într-un singur fișier și rulat live. Astfel, se poate testa trimiterea mesajelor fără să fie nevoie de setări suplimentare, doar cu un server local care suportă mail() sau cu configurarea unui SMTP local.

Login / Register cu hashing & sesiuni

Pentru a crea un sistem sigur de autentificare, folosim password_hash() la înregistrare și password_verify() la login. Datele utilizatorilor se stochează într-o bază de date (de ex. tabela users), iar sesiunea este folosită pentru a păstra starea de autentificare.

Actualizare tabela users pentru login

Adăugăm coloana password în tabela users astfel încât să putem stoca parola hashed:

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

Varianta PHP pentru a rula dintr-un script și a verifica dacă coloana există:

<?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 "✅ Coloana 'password' a fost adăugată în tabela 'users'.";
} catch (PDOException $e) {
    echo "❌ Eroare: " . $e->getMessage();
}
?>

După ce coloana este adăugată, exemplul de login și register va funcționa corect.

Exemplu PHP - 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 = "Toate câmpurile sunt obligatorii.";
    } elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $register_msg = "Email invalid.";
    } 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 = "✅ Cont creat cu succes!";
        } else {
            $register_msg = "❌ Eroare la crearea contului.";
        }
    }
}
?>

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

<form method="post">
    <input type="text" name="username" placeholder="Nume" required><br>
    <input type="email" name="email" placeholder="Email" required><br>
    <input type="password" name="password" placeholder="Parolă" required><br>
    <button type="submit" name="register">Înregistrează-te</button>
</form>

Exemplu PHP - 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 = "✅ Autentificare reușită! Bun venit, " . htmlspecialchars($user['name']);
    } else {
        $login_msg = "❌ Email sau parolă incorectă.";
    }
}
?>

<h3>Formular Login</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="Parolă" required><br>
    <button type="submit" name="login">Autentifică-te</button>
</form>

Acest cod poate fi pus într-un singur fișier, pentru a testa înregistrarea și login-ul live. Sesiunile permit păstrarea autentificării între pagini și securizează accesul la zonele protejate.

🔧 Exemplu PHP: 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 = "Toate câmpurile sunt obligatorii.";
    } elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $register_msg = "Email invalid.";
    } 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 = "✅ Cont creat cu succes!";
        } else {
            $register_msg = "❌ Eroare la crearea contului.";
        }
    }
}
?>

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

<form method="post">
    <input type="text" name="username" placeholder="Nume" required><br>
    <input type="email" name="email" placeholder="Email" required><br>
    <input type="password" name="password" placeholder="Parolă" required><br>
    <button type="submit" name="register">Înregistrează-te</button>
</form>


🔧 Exemplu PHP: 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 = "✅ Autentificare reușită! Bun venit, " . htmlspecialchars($user['name']);
    } else {
        $login_msg = "❌ Email sau parolă incorectă.";
    }
}
?>

<h3>Formular Login</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="Parolă" required><br>
    <button type="submit" name="login">Autentifică-te</button>
</form>

Flash Messages în PHP

Flash messages sunt mesaje temporare care apar o singură dată după o acțiune (ex: login reușit, eroare la formular) și dispar după reîncărcarea paginii. Ele sunt de obicei stocate în sesiune.

Exemplu practic: Flash message după login

<?php
session_start();

// Setare mesaj flash după login
$_SESSION['flash_message'] = "✅ Ai fost logat cu succes!";

// Redirecționare către pagina principală
header("Location: index.php");
exit;
?>
<?php
session_start();

// Afișare mesaj flash și ștergere după afișare
if(isset($_SESSION['flash_message'])) {
    echo "<div class='flash'>" . $_SESSION['flash_message'] . "</div>";
    unset($_SESSION['flash_message']);
}
?>

Astfel, mesajul va fi vizibil doar o singură dată, apoi dispare automat.

Like / Dislike Posts

Pentru a implementa funcționalitatea de like/dislike, avem nevoie de o tabelă suplimentară care să stocheze acțiunile utilizatorilor asupra postărilor.

Pregătirea bazei de date pentru exemple

1. Creează un fișier numit update-db.php în folderul proiectului tău PHP.

2. Copiază în el codul de mai jos (cel care creează baza de date traffice-test, tabelele users, posts, post_likes și adaugă date de test).

3. Deschide browserul și rulează fișierul astfel:

http://localhost/numele-folderului/update-db.php

4. Dacă totul e în regulă, vei vedea mesajul:

✅ Baza de date și tabelele au fost create cu date de test funcționale.

5. Acum ai toate tabelele și datele pregătite pentru a rula exemplele de: CRUD, Flash messages și Like/Dislike posts.

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

    // Creare baza de date
    $pdo->exec("CREATE DATABASE IF NOT EXISTS traffice-test CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
    $pdo->exec("USE traffice-test");

    // Creare tabela users
    $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
    )");

    // Inserare useri
    $pdo->exec("INSERT INTO users (id, name, email, password) VALUES
        (1, 'Ion Popescu', 'ion.popescu@example.com', '123'),
        (2, 'Maria Ionescu', 'maria.ionescu@example.com', '123')
        ON DUPLICATE KEY UPDATE name=VALUES(name), email=VALUES(email)");

    // Creare tabela posts
    $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
    )");

    // Inserare postari
    $pdo->exec("INSERT INTO posts (id, user_id, title, content) VALUES
        (1, 1, 'Primul articol', 'Acesta este primul post scris de utilizatorul 1.'),
        (2, 1, 'Al doilea articol', 'Utilizatorul 1 mai are o postare.'),
        (3, 2, 'Salutare!', 'Mesaj scris de utilizatorul 2.')
        ON DUPLICATE KEY UPDATE title=VALUES(title), content=VALUES(content)");

    // Creare tabela post_likes
    $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 "✅ Baza de date și tabelele au fost create cu date de test funcționale.";

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

Exemplu PHP pentru 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; // ID post
$user_id = 1; // ID utilizator
$type = 'like'; // sau 'dislike'

// Inserare 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]);

// Număr total like-uri și dislike-uri pentru un 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>";
}
?>

Astfel, utilizatorii pot da like sau dislike, iar numărul total se actualizează automat. Funcția `ON DUPLICATE KEY UPDATE` asigură că un utilizator nu poate da like și dislike simultan pe aceeași postare.

🔧 Exemplu PHP: like sau dislike
<?php
// Conectare la baza de date
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("Eroare conectare DB: " . $e->getMessage());
}

// Procesare 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]);
}

// Preluare postări și număr like/dislike
$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);

// Lista de utilizatori (pentru demo: user_id select)
$users = $pdo->query("SELECT * FROM users")->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="ro">
<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 Postări</h1>

<form method="post">
    <label for="user_id">Selectează utilizatorul:</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>Scris de <?php echo htmlspecialchars($post['name']); ?> (<?php echo htmlspecialchars($post['email']); ?>) la <?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