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

Ce este MySQL și cum îl accesăm din PHP

MySQL este un sistem de gestiune a bazelor de date relaționale (RDBMS). Asta înseamnă că stochează datele în tabele (rânduri și coloane) și îți oferă limbajul SQL pentru a crea tabele, a introduce, căuta, modifica și șterge date. MySQL rulează ca un server (un proces separat), iar aplicația ta PHP se conectează la el prin rețea (de obicei la localhost, portul 3306 pe mașina ta).

Termeni esențiali (pe scurt)

Ce este SQL (pe înțelesul tuturor)

SQL (Structured Query Language) este limbajul standard pentru a lucra cu date relaționale. Are comenzi pentru:

Exemple SQL ultra-simple

-- Creează o bază de date 
CREATE DATABASE curs_php CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- Alege baza de date
USE curs_php;

-- Creează un tabel
CREATE TABLE users (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(150) NOT NULL UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;

-- Citește toți utilizatorii
SELECT id, name, email FROM users;

De ce MySQL pentru proiecte PHP?

Instalare & pornire (pe scurt)

Cum accesăm MySQL din PHP (opțiuni)

Recomandare: folosește PDO pentru portabilitate, securitate și o API coerentă.

Conectare la MySQL cu PDO (recomandat)

Formatul DSN pentru MySQL: mysql:host=HOST;dbname=BAZA; charset=UTF8. Setăm și opțiuni pentru erori și fetch.

<?php $host = '127.0.0.1'; // sau 
'localhost' $db = 'curs_php';// numele bazei de date
$user = 'root'; //userul 
MySQL $pass = ''; //parola (la XAMPP e de obicei goală) $charset = 'utf8mb4';

$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // aruncă excepții la erori
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // fetch ca array asociativ
PDO::ATTR_EMULATE_PREPARES => false, // prepared statements reale
];

try {
$pdo = new PDO($dsn, $user, $pass, $options);
echo "✅ Conexiune reușită la baza de date!";
} catch (PDOException $e) {
echo "❌ Eroare de conexiune: " . $e->getMessage();
}
?>

Separarea credențialelor (config separat)

Nu ține datele de conectare împrăștiate prin cod. Folosește un fișier config.php pe care îl incluzi unde ai nevoie.

config.php

<?php return [ 'db' => [ 'host' => '127.0.0.1', 'name' => 'curs_php', 'user' => 'root', 'pass' => '', 'charset' => 'utf8mb4', ], ]; ?> 

db.php (factory de conexiune)

<?php $config = require __DIR__ . '/config.php'; $db = $config['db'];

$dsn = "mysql:host={$db['host']};dbname={$db['name']};charset={$db['charset']}";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];

try {
$pdo = new PDO($dsn, $db['user'], $db['pass'], $options);
} catch (PDOException $e) {
exit('Eroare conectare DB: ' . $e->getMessage());
}
?>

test-conn.php (verificare rapidă)

<?php require __DIR__ . '/db.php';

$versiune = $pdo->query('SELECT VERSION()')->fetchColumn();
echo "Conectat la MySQL versiunea: " . $versiune;
?>

Erori frecvente & cum le rezolvi

Bune practici de bază (securitate)

Conectare la baza de date folosind PDO

Pentru a lucra cu o bază de date MySQL din PHP, cea mai sigură și flexibilă metodă este PDO (PHP Data Objects). Aceasta oferă o interfață unificată pentru mai multe tipuri de baze de date (nu doar MySQL), sprijină prepared statements (care protejează împotriva atacurilor SQL Injection) și oferă metode avansate de lucru.

Sintaxa de bază pentru conexiune

O conexiune PDO necesită: numele serverului (host), numele bazei de date (dbname), numele de utilizator și parola. Este recomandat să folosim blocuri try...catch pentru a captura eventualele erori de conexiune.


// Datele de conectare
$host = "localhost";
$dbname = "testdb";
$username = "root";
$password = "";

try {
    // Creăm obiectul PDO
    $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $username, $password);
    
    // Setăm modul de raportare a erorilor
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    echo "✅ Conexiunea la baza de date a reușit!";
} catch (PDOException $e) {
    echo "❌ Conexiunea a eșuat: " . $e->getMessage();
}

Explicații

  • new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $username, $password) - stabilește conexiunea la MySQL.
  • setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) - configurăm PDO să arunce excepții în caz de erori (mai ușor de depistat problemele).
  • try...catch - dacă apare o eroare (ex. parola greșită), aceasta va fi prinsă și afișată în $e->getMessage().

Exemplu concret: Crearea bazei de date și a tabelelor

Înainte de a putea salva informații într-o aplicație PHP, avem nevoie de o bază de date. Noi vom folosi MySQL, care vine deja instalat în pachetul XAMPP.

1. Pornirea serverului MySQL

- Deschide XAMPP Control Panel. - Pornește modulele Apache și MySQL. Acum serverul web și serverul de baze de date rulează pe calculatorul tău.

2. Crearea bazei de date (varianta simplă prin phpMyAdmin)

Accesează http://localhost/phpmyadmin în browser. Acolo ai o interfață grafică unde poți apăsa pe tab-ul Databases și să creezi manual baza de date traffice-test. Aceasta este cea mai ușoară metodă pentru începători.

3. Crearea bazei de date din PHP

Dacă vrei să creezi baza de date direct printr-un script PHP, atunci faci așa:

<?php
try {
    // Conectare la MySQL (fără a specifica încă baza de date)
    $pdo = new PDO("mysql:host=localhost", "root", "");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // Comanda SQL pentru a crea baza de date
    $sql = "CREATE DATABASE IF NOT EXISTS traffice-test";
    $pdo->exec($sql);

    echo "✅ Baza de date 'traffice-test' a fost creată cu succes.";
} catch (PDOException $e) {
    echo "❌ Eroare la crearea bazei de date: " . $e->getMessage();
}
?>

Unde pui acest cod?

1. Deschizi folderul htdocs din directorul XAMPP (ex: C:\xampp\htdocs).
2. Creezi un fișier nou, de exemplu create_db.php.
3. Pui în el codul de mai sus.
4. În browser accesezi http://localhost/create_db.php.
Dacă totul este în regulă, pe ecran vei vedea mesajul Baza de date 'traffice-test' a fost creată cu succes.

4. Verificarea bazei de date

Pentru a confirma că baza de date există, mergi în phpMyAdmin (http://localhost/phpmyadmin) și ar trebui să vezi traffice-test în lista din stânga.

Crearea tabelului users în baza de date

După ce avem baza de date traffice-test, următorul pas este să creăm un tabel în care să stocăm informațiile. Vom crea un tabel simplu numit users, care va avea următoarele coloane:

  • id - identificator unic pentru fiecare utilizator (cheie primară, auto-increment)
  • name - numele utilizatorului (text)
  • email - adresa de email (text, unică)

1. Comanda SQL pentru crearea tabelului

Aceasta este comanda SQL clasică:

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) NOT NULL UNIQUE
);

2. Crearea tabelului printr-un script PHP

Putem executa comanda SQL dintr-un fișier PHP. Creăm un fișier nou, de exemplu create_table.php în htdocs:

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

    // Crearea tabelului users
    $sql = "CREATE TABLE IF NOT EXISTS users (
                id INT AUTO_INCREMENT PRIMARY KEY,
                name VARCHAR(100) NOT NULL,
                email VARCHAR(100) NOT NULL UNIQUE
            )";

    $pdo->exec($sql);

    echo "✅ Tabelul 'users' a fost creat cu succes.";
} catch (PDOException $e) {
    echo "❌ Eroare la crearea tabelului: " . $e->getMessage();
}
?>

3. Cum rulăm scriptul?

1. Salvează fișierul create_table.php în C:\xampp\htdocs.
2. Deschide browserul și mergi la http://localhost/create_table.php.
3. Dacă totul a mers bine, vei vedea mesajul Tabelul 'users' a fost creat cu succes.

4. Verificarea tabelului

Intră din nou în phpMyAdmin → baza de date traffice-test și ar trebui să vezi tabelul users în lista din stânga. Poți da click pe el și vei observa coloanele id, name și email.

Explicații

  • AUTO_INCREMENT - fiecare utilizator primește un ID unic automat.
  • NOT NULL - câmpul nu poate rămâne gol.
  • UNIQUE - fiecare email trebuie să fie unic în tabel (nu se pot înregistra două conturi cu același email).
  • IF NOT EXISTS - evită eroarea dacă tabelul există deja.

Operații CRUD în PHP & MySQL

CRUD este acronimul pentru cele patru operații fundamentale pe care le putem efectua asupra datelor într-o bază de date: Create (Creare), Read (Citire), Update (Actualizare), Delete (Ștergere).

1. Create (Creare)

Operația CREATE înseamnă adăugarea de noi înregistrări (rânduri) într-un tabel. În PHP, acest lucru se face folosind o interogare SQL INSERT INTO. De exemplu, putem adăuga un utilizator nou în tabela users cu nume și email.

2. Read (Citire)

Operația READ înseamnă citirea și afișarea datelor existente. În PHP folosim interogarea SELECT, care poate returna toți utilizatorii sau doar anumite coloane/înregistrări filtrate.

3. Update (Actualizare)

Operația UPDATE este folosită pentru a modifica datele existente. Putem actualiza numele sau adresa de email a unui utilizator folosind o interogare SQL UPDATE cu o condiție WHERE.

4. Delete (Ștergere)

Operația DELETE șterge o înregistrare din tabel. Este foarte important să folosim întotdeauna o condiție WHERE pentru a evita ștergerea tuturor datelor.

Operații CRUD în PHP & MySQL (tabelul users)

Presupunem că avem deja baza de date traffice-test și tabela users creată. Mai jos demonstrăm cele 4 operații fundamentale: INSERT (Create), SELECT (Read), UPDATE, DELETE. Tot codul este într-un singur fișier crud_demo.php.


<?php
try {
    // 1. Conectare la baza de date

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

    echo "<h2>CRUD pe tabela users</h2>";

    // CREATE - Adăugăm utilizatori noi

    $pdo->exec("INSERT INTO users (name, email) VALUES ('Ion Popescu', 'ion@example.com')");
    $pdo->exec("INSERT INTO users (name, email) VALUES ('Maria Ionescu', 'maria@example.com')");
    echo "<p>✅ Utilizatori adăugați.</p>";

    // READ - Afișăm toți utilizatorii

    echo "<h3>Lista utilizatori:</h3>";
    $stmt = $pdo->query("SELECT * FROM users");
    foreach ($stmt as $row) {
        echo $row['id'] . " - " . $row['name'] . " (" . $row['email'] . ")<br>";
    }
  
    // UPDATE - Modificăm emailul lui Ion

    $pdo->exec("UPDATE users SET email='ion.popescu@nou.com' WHERE name='Ion Popescu'");
    echo "<p>✅ Emailul lui Ion a fost actualizat.</p>";

    // Citim din nou după UPDATE
    echo "<h3>După Update:</h3>";
    $stmt = $pdo->query("SELECT * FROM users");
    foreach ($stmt as $row) {
        echo $row['id'] . " - " . $row['name'] . " (" . $row['email'] . ")<br>";
    }

    // DELETE - Ștergem utilizatorul Maria
 
    $pdo->exec("DELETE FROM users WHERE name='Maria Ionescu'");
    echo "<p>✅ Maria a fost ștearsă.</p>";

    // Citim după DELETE
    echo "<h3>După Delete:</h3>";
    $stmt = $pdo->query("SELECT * FROM users");
    foreach ($stmt as $row) {
        echo $row['id'] . " - " . $row['name'] . " (" . $row['email'] . ")<br>";
    }

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

Exemplu practic CRUD (HTML + PHP)

Mai jos avem un exemplu complet de aplicație simplă CRUD pentru tabela users. Aceasta permite adăugarea de utilizatori noi, afișarea listei de utilizatori, actualizarea și ștergerea lor.

🔧 Exemplu complet de aplicație simplă CRUD pentru tabela users
<?php
// db.php - conexiunea la baza de date
$pdo = new PDO("mysql:host=localhost;dbname=traffice-test", "traffice_php", "!@y3Ge-Z!WQI");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// Adăugare utilizator
if (isset($_POST['add'])) {
    $name = $_POST['name'];
    $email = $_POST['email'];
    $stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
    $stmt->execute([$name, $email]);
}

// Ștergere utilizator
if (isset($_GET['delete'])) {
    $id = $_GET['delete'];
    $stmt = $pdo->prepare("DELETE FROM users WHERE id = ?");
    $stmt->execute([$id]);
}

// Actualizare utilizator
if (isset($_POST['update'])) {
    $id = $_POST['id'];
    $name = $_POST['name'];
    $email = $_POST['email'];
    $stmt = $pdo->prepare("UPDATE users SET name=?, email=? WHERE id=?");
    $stmt->execute([$name, $email, $id]);
}

// Citire utilizatori
$stmt = $pdo->query("SELECT * FROM users");
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>

<!DOCTYPE html>
<html>
<head>
    <title>CRUD Demo</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        table { border-collapse: collapse; width: 60%; margin-top: 20px; }
        th, td { border: 1px solid #ccc; padding: 8px; text-align: center; }
        form { margin-bottom: 20px; }
    </style>
</head>
<body>
    <h2>Adaugă utilizator</h2>
    <form method="post">
        <input type="text" name="name" placeholder="Nume" required>
        <input type="email" name="email" placeholder="Email" required>
        <button type="submit" name="add">Adaugă</button>
    </form>

    <h2>Lista utilizatori</h2>
    <table>
        <tr>
            <th>ID</th><th>Nume</th><th>Email</th><th>Acțiuni</th>
        </tr>
        <?php foreach ($users as $user): ?>
        <tr>
            <td><?= $user['id'] ?></td>
            <td><?= $user['name'] ?></td>
            <td><?= $user['email'] ?></td>
            <td>
                <!-- Formular pentru update -->
                <form method="post" style="display:inline;">
                    <input type="hidden" name="id" value="<?= $user['id'] ?>">
                    <input type="text" name="name" value="<?= $user['name'] ?>" required>
                    <input type="email" name="email" value="<?= $user['email'] ?>" required>
                    <br><br>
                    <button type="submit" name="update">Actualizează</button>
                </form>
                <!-- Link pentru delete -->
                <br>
                <a href="?delete=<?= $user['id'] ?>" onclick="return confirm('Sigur ștergi?')">Șterge</a>
            </td>
        </tr>
        <?php endforeach; ?>
    </table>
</body>
</html>

Prepared Statements în PHP (Prevenirea SQL Injection)

O problemă frecventă în aplicațiile web este SQL Injection, adică introducerea intenționată de cod SQL malițios în câmpurile de input pentru a manipula baza de date. Dacă nu validăm și nu securizăm datele trimise de utilizatori, aplicația poate fi compromisă.

Exemplu de query vulnerabil (Așa NU!)

<?php
// Exemplu nesigur (NU faceți așa!)
$name = $_POST['name'];
$sql = "SELECT * FROM users WHERE name = '$name'";
$stmt = $pdo->query($sql); // Vulnerabil la SQL Injection
?>

Dacă un utilizator introduce valoarea ' OR '1'='1 în câmpul name, query-ul va deveni:


SELECT * FROM users WHERE name = '' OR '1'='1';

Rezultatul? Toți utilizatorii din baza de date vor fi returnați! ⚠️

Soluția: Prepared Statements

Pentru a preveni atacurile de tip SQL Injection, folosim prepared statements (instrucțiuni pregătite). Acestea separă logica SQL de datele introduse de utilizator. Astfel, valorile sunt tratate ca simple date, nu ca instrucțiuni SQL.

Exemplu corect cu PDO (parametri anonimi)

<?php
// Folosind PDO cu placeholderi ?
$stmt = $pdo->prepare("SELECT * FROM users WHERE name = ?");
$stmt->execute([$_POST['name']]);
$results = $stmt->fetchAll();

foreach ($results as $row) {
    echo $row['id'] . " - " . $row['name'] . " - " . $row['email'] . "<br>";
}
?>

Exemplu corect cu PDO (parametri denumiți)

<?php
// Folosind PDO cu placeholderi denumiți
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
$stmt->bindParam(':email', $_POST['email'], PDO::PARAM_STR);
$stmt->execute();
$results = $stmt->fetchAll();

foreach ($results as $row) {
    echo $row['id'] . " - " . $row['name'] . " - " . $row['email'] . "<br>";
}
?>

Observați că acum chiar dacă un utilizator încearcă să introducă text malițios, acesta va fi tratat ca simplă valoare de text și nu va putea altera query-ul SQL.

Exemplu complet CRUD cu Prepared Statements (Tabelul users)

Acum că știm cât de importantă este securitatea, vom implementa toate operațiile CRUD (Create, Read, Update, Delete) folosind Prepared Statements. Exemplul folosește tabela users cu câmpurile: id (AUTO_INCREMENT, PRIMARY KEY), name, email.

Cod PHP + HTML pentru CRUD


<?php
// Conectare la baza de date
$pdo = new PDO("mysql:host=localhost;dbname=traffice-test", "root", "");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// CREATE: Inserare utilizator nou
if (isset($_POST['add'])) {
    $stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (:name, :email)");
    $stmt->execute([
        ':name' => $_POST['name'],
        ':email' => $_POST['email']
    ]);
}

// UPDATE: Modificare utilizator
if (isset($_POST['update'])) {
    $stmt = $pdo->prepare("UPDATE users SET name = :name, email = :email WHERE id = :id");
    $stmt->execute([
        ':name' => $_POST['name'],
        ':email' => $_POST['email'],
        ':id' => $_POST['id']
    ]);
}

// DELETE: Ștergere utilizator
if (isset($_POST['delete'])) {
    $stmt = $pdo->prepare("DELETE FROM users WHERE id = :id");
    $stmt->execute([':id' => $_POST['id']]);
}

// READ: Afișare toți utilizatorii
$stmt = $pdo->query("SELECT * FROM users ORDER BY id ASC");
$users = $stmt->fetchAll();
?>

<!DOCTYPE html>
<html lang="ro">
<head>
    <meta charset="UTF-8">
    <title>CRUD Demo</title>
    <style>
        table { border-collapse: collapse; width: 50%; margin-top: 20px; }
        table, th, td { border: 1px solid black; padding: 8px; text-align: left; }
        form { margin-top: 20px; }
    </style>
</head>
<body>
    <h2>Gestionare utilizatori</h2>

    <!-- Formular adăugare utilizator -->
    <h3>Adaugă utilizator</h3>
    <form method="post">
        Nume: <input type="text" name="name" required>
        Email: <input type="email" name="email" required>
        <button type="submit" name="add">Adaugă</button>
    </form>

    <!-- Tabel utilizatori -->
    <h3>Lista utilizatori</h3>
    <table>
        <tr><th>ID</th><th>Nume</th><th>Email</th><th>Acțiuni</th></tr>
        <?php foreach ($users as $user): ?>
            <tr>
                <td><?= $user['id'] ?></td>
                <td><?= htmlspecialchars($user['name']) ?></td>
                <td><?= htmlspecialchars($user['email']) ?></td>
                <td>
                    <!-- Formular UPDATE -->
                    <form method="post" style="display:inline;">
                        <input type="hidden" name="id" value="<?= $user['id'] ?>">
                        Nume: <input type="text" name="name" value="<?= htmlspecialchars($user['name']) ?>" required>
                        Email: <input type="email" name="email" value="<?= htmlspecialchars($user['email']) ?>" required>
                        <button type="submit" name="update">Modifică</button>
                    </form>

                    <!-- Formular DELETE -->
                    <form method="post" style="display:inline;">
                        <input type="hidden" name="id" value="<?= $user['id'] ?>">
                        <button type="submit" name="delete" onclick="return confirm('Ștergi utilizatorul?')">Șterge</button>
                    </form>
                </td>
            </tr>
        <?php endforeach; ?>
    </table>
</body>
</html>
🔧 Cod PHP + HTML pentru CRUD
<?php
// Conectare la baza de date
$pdo = new PDO("mysql:host=localhost;dbname=traffice-test", "traffice_php", "!@y3Ge-Z!WQI");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// CREATE: Inserare utilizator nou
if (isset($_POST['add'])) {
    $stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (:name, :email)");
    $stmt->execute([
        ':name' => $_POST['name'],
        ':email' => $_POST['email']
    ]);
}

// UPDATE: Modificare utilizator
if (isset($_POST['update'])) {
    $stmt = $pdo->prepare("UPDATE users SET name = :name, email = :email WHERE id = :id");
    $stmt->execute([
        ':name' => $_POST['name'],
        ':email' => $_POST['email'],
        ':id' => $_POST['id']
    ]);
}

// DELETE: Ștergere utilizator
if (isset($_POST['delete'])) {
    $stmt = $pdo->prepare("DELETE FROM users WHERE id = :id");
    $stmt->execute([':id' => $_POST['id']]);
}

// READ: Afișare toți utilizatorii
$stmt = $pdo->query("SELECT * FROM users ORDER BY id ASC");
$users = $stmt->fetchAll();
?>

<!DOCTYPE html>
<html lang="ro">
<head>
    <meta charset="UTF-8">
    <title>CRUD Demo</title>
    <style>
        table { border-collapse: collapse; width: 50%; margin-top: 20px; }
        table, th, td { border: 1px solid black; padding: 8px; text-align: left; }
        form { margin-top: 20px; }
    </style>
</head>
<body>
    <h2>Gestionare utilizatori</h2>

    <!-- Formular adăugare utilizator -->
    <h3>Adaugă utilizator</h3>
    <form method="post">
        Nume: <input type="text" name="name" required>
        Email: <input type="email" name="email" required>
        <button type="submit" name="add">Adaugă</button>
    </form>

    <!-- Tabel utilizatori -->
    <h3>Lista utilizatori</h3>
    <table>
        <tr><th>ID</th><th>Nume</th><th>Email</th><th>Acțiuni</th></tr>
        <?php foreach ($users as $user): ?>
            <tr>
                <td><?= $user['id'] ?></td>
                <td><?= htmlspecialchars($user['name']) ?></td>
                <td><?= htmlspecialchars($user['email']) ?></td>
                <td>
                    <!-- Formular UPDATE -->
                    <form method="post" style="display:inline;">
                        <input type="hidden" name="id" value="<?= $user['id'] ?>">
                        Nume: <input type="text" name="name" value="<?= htmlspecialchars($user['name']) ?>" required>
                        Email: <input type="email" name="email" value="<?= htmlspecialchars($user['email']) ?>" required>
                        <button type="submit" name="update">Modifică</button>
                    </form>

                    <!-- Formular DELETE -->
                    <form method="post" style="display:inline;">
                        <input type="hidden" name="id" value="<?= $user['id'] ?>">
                        <button type="submit" name="delete" onclick="return confirm('Ștergi utilizatorul?')">Șterge</button>
                    </form>
                </td>
            </tr>
        <?php endforeach; ?>
    </table>
</body>
</html>

Relații între tabele (Users - Posts)

Într-o aplicație reală, tabelele din baza de date nu există izolat. De cele mai multe ori, ele sunt legate între ele prin chei primare și chei externe (primary key & foreign key). De exemplu, într-o aplicație de tip blog, avem:

  • users - stochează informațiile despre utilizatori (id, nume, email);
  • posts - stochează articolele sau mesajele publicate de utilizatori.

Legătura dintre cele două tabele este de tip 1 la N (un utilizator poate avea mai multe postări). Această legătură se face printr-o coloană user_id în tabela posts, care face referire la id din tabela users.

Crearea tabelei posts

Putem crea tabela fie din phpMyAdmin cu SQL simplu, fie direct printr-un script PHP. În phpMyAdmin rulăm codul de mai jos:

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

Sau rulează dintr-un fișier php:

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

    $sql = "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
            )";
    $pdo->exec($sql);

    echo "✅ Tabela 'posts' a fost creată.";
} catch (PDOException $e) {
    echo "❌ Eroare: " . $e->getMessage();
}
?>

Inserarea unor date de test

În phpMyAdmin rulăm codul de mai jos:

Inserăm mai întâi utilizatorii în tabela users:

INSERT INTO users (name, email) VALUES
('Ion Popescu', 'ion.popescu@example.com'),
('Maria Ionescu', 'maria.ionescu@example.com');

Abia apoi inserăm postările legate de acei useri:

INSERT INTO posts (user_id, title, content) VALUES
(1, 'Primul articol', 'Acesta este primul post scris de utilizatorul 1.'),
(1, 'Al doilea articol', 'Utilizatorul 1 mai are o postare.'),
(2, 'Salutare!', 'Mesaj scris de utilizatorul 2.');

Afișarea postărilor împreună cu utilizatorii

Putem folosi un JOIN pentru a obține într-un singur query atât datele despre utilizator, cât și postările lui.

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

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

    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        echo "<h4>" . htmlspecialchars($row['title']) . "</h4>";
        echo "<p>" . htmlspecialchars($row['content']) . "</p>";
        echo "<small>Scris de: " . htmlspecialchars($row['name']) . " (" . htmlspecialchars($row['email']) . ") la " . $row['created_at'] . "</small><hr>";
    }
} catch (PDOException $e) {
    echo "Eroare: " . $e->getMessage();
}
?>
🔧 Exemplu PHP: Afișarea postărilor împreună cu utilizatorii
<?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, posts.title, posts.content, posts.created_at, users.name, users.email
            FROM posts
            INNER JOIN users ON posts.user_id = users.id
            ORDER BY posts.created_at DESC";
    $stmt = $pdo->query($sql);

    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        echo "<h4>" . htmlspecialchars($row['title']) . "</h4>";
        echo "<p>" . htmlspecialchars($row['content']) . "<p>";
        echo "<small>Scris de: " . htmlspecialchars($row['name']) . " (" . htmlspecialchars($row['email']) . ") la " . $row['created_at'] . "</small><hr>";
    }
} catch (PDOException $e) {
    echo "Eroare: " . $e->getMessage();
}
?>

Demo live: Users & Posts

Acest exemplu arată cum putem adăuga utilizatori și postări și cum le afișăm împreună.

<?php
// Conectare la baza de date
$pdo = new PDO("mysql:host=localhost;dbname=traffice-test", "root", "");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// Adăugare utilizator
if(isset($_POST['add_user'])) {
    $name = $_POST['name'];
    $email = $_POST['email'];
    if($name && $email) {
        $stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
        $stmt->execute([$name, $email]);
        echo "<p style='color:green;'>✅ Utilizator adăugat!</p>";
    }
}

// Ștergere utilizator
if(isset($_GET['delete_user'])) {
    $id = (int)$_GET['delete_user'];
    $stmt = $pdo->prepare("DELETE FROM users WHERE id=?");
    $stmt->execute([$id]);
    echo "<p style='color:red;'>🗑️ Utilizator șters!</p>";
}

// Adăugare postare
if(isset($_POST['add_post'])) {
    $user_id = $_POST['user_id'];
    $title = $_POST['title'];
    $content = $_POST['content'];
    if($user_id && $title && $content) {
        $stmt = $pdo->prepare("INSERT INTO posts (user_id, title, content) VALUES (?, ?, ?)");
        $stmt->execute([$user_id, $title, $content]);
        echo "<p style='color:green;'>✅ Postare adăugată!</p>";
    }
}

// Ștergere postare
if(isset($_GET['delete_post'])) {
    $id = (int)$_GET['delete_post'];
    $stmt = $pdo->prepare("DELETE FROM posts WHERE id=?");
    $stmt->execute([$id]);
    echo "<p style='color:red;'>🗑️ Postare ștearsă!</p>";
}

// Preluare utilizatori pentru formular
$users = $pdo->query("SELECT id, name FROM users")->fetchAll(PDO::FETCH_ASSOC);
?>

<h3 class="subtitle">Adaugă utilizator nou</h3>
<form method="post">
    Nume: <input type="text" name="name" required>
    Email: <input type="email" name="email" required>
    <button type="submit" name="add_user">Adaugă utilizator</button>
</form>

<h3 class="subtitle">Adaugă postare nouă</h3>
<form method="post">
    Utilizator:
    <select name="user_id" required>
        <?php foreach($users as $u) { ?>
            <option value="<?= $u['id'] ?>"><?= htmlspecialchars($u['name']) ?></option>
        <?php } ?>
    </select>
    Titlu: <input type="text" name="title" required>
    Conținut: <textarea name="content" required></textarea>
    <button type="submit" name="add_post">Adaugă postare</button>
</form>

<h3 class="subtitle">Lista utilizatorilor</h3>
<table>
    <tr><th>ID</th><th>Nume</th><th>Email</th><th>Acțiuni</th></tr>
    <?php
    $stmt = $pdo->query("SELECT id, name, email FROM users");
    while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        echo "<tr><td>".$row['id']."</td><td>".htmlspecialchars($row['name'])."</td><td>".htmlspecialchars($row['email'])."</td><td><a href='?delete_user=".$row['id']."' onclick='return confirm(\"Sigur vrei să ștergi?\")'>Șterge</a></td></tr>";
    }
    ?>
</table>

<h3 class="subtitle">Postările utilizatorilor</h3>
<?php
$sql = "SELECT posts.id, posts.title, posts.content, users.name, users.email, posts.created_at
        FROM posts
        INNER JOIN users ON posts.user_id = users.id
        ORDER BY posts.created_at DESC";
$stmt = $pdo->query($sql);

while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    echo "<h4>".htmlspecialchars($row['title'])."</h4>";
    echo "<p>".htmlspecialchars($row['content'])."</p>";
    echo "<small>Scris de: ".htmlspecialchars($row['name'])." (".htmlspecialchars($row['email']).") la ".$row['created_at']."</small>";
    echo " <a href='?delete_post=".$row['id']."' onclick='return confirm(\"Sigur vrei să ștergi?\")'>🗑️ Șterge</a><hr>";
}
?>
🔧 Exemplu PHP: Demo live: Users & Posts
<?php
// Conectare la baza de date
$pdo = new PDO("mysql:host=localhost;dbname=traffice-test", "traffice_php", "!@y3Ge-Z!WQI");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// Adăugare utilizator
if(isset($_POST['add_user'])) {
    $name = $_POST['name'];
    $email = $_POST['email'];
    if($name && $email) {
        $stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
        $stmt->execute([$name, $email]);
        echo "<p style='color:green;'>✅ Utilizator adăugat!<p>";
    }
}

// Ștergere utilizator
if(isset($_GET['delete_user'])) {
    $id = (int)$_GET['delete_user'];
    $stmt = $pdo->prepare("DELETE FROM users WHERE id=?");
    $stmt->execute([$id]);
    echo "<p style='color:red;'>🗑️ Utilizator șters!<p>";
}

// Adăugare postare
if(isset($_POST['add_post'])) {
    $user_id = $_POST['user_id'];
    $title = $_POST['title'];
    $content = $_POST['content'];
    if($user_id && $title && $content) {
        $stmt = $pdo->prepare("INSERT INTO posts (user_id, title, content) VALUES (?, ?, ?)");
        $stmt->execute([$user_id, $title, $content]);
        echo "<p style='color:green;'>✅ Postare adăugată!<p>";
    }
}

// Ștergere postare
if(isset($_GET['delete_post'])) {
    $id = (int)$_GET['delete_post'];
    $stmt = $pdo->prepare("DELETE FROM posts WHERE id=?");
    $stmt->execute([$id]);
    echo "<p style='color:red;'>🗑️ Postare ștearsă!<p>";
}

// Preluare utilizatori pentru formular
$users = $pdo->query("SELECT id, name FROM users")->fetchAll(PDO::FETCH_ASSOC);
?>

<h3 class="subtitle">Adaugă utilizator nou</h3>
<form method="post">
    Nume: <input type="text" name="name" required>
    Email: <input type="email" name="email" required>
    <button type="submit" name="add_user">Adaugă utilizator</button>
</form>

<h3 class="subtitle">Adaugă postare nouă</h3>
<form method="post">
    Utilizator:
    <select name="user_id" required>
        <?php foreach($users as $u) { ?>
            <option value="<?= $u['id'] ?>"><?= htmlspecialchars($u['name']) ?></option>
        <?php } ?>
    </select>
    Titlu: <input type="text" name="title" required>
    Conținut: <textarea name="content" required></textarea>
    <button type="submit" name="add_post">Adaugă postare</button>
</form>

<h3 class="subtitle">Lista utilizatorilor</h3>
<table>
    <tr><th>ID</th><th>Nume</th><th>Email</th><th>Acțiuni</th></tr>
    <?php
    $stmt = $pdo->query("SELECT id, name, email FROM users");
    while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        echo "<tr><td>".$row['id']."</td><td>".htmlspecialchars($row['name'])."</td><td>".htmlspecialchars($row['email'])."</td><td><a href='?delete_user=".$row['id']."' onclick='return confirm(\"Sigur vrei să ștergi?\")'>Șterge</a></td></tr>";
    }
    ?>
</table>

<h3 class="subtitle">Postările utilizatorilor</h3>
<?php
$sql = "SELECT posts.id, posts.title, posts.content, users.name, users.email, posts.created_at
        FROM posts
        INNER JOIN users ON posts.user_id = users.id
        ORDER BY posts.created_at DESC";
$stmt = $pdo->query($sql);

while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    echo "<h4>".htmlspecialchars($row['title'])."</h4>";
    echo "<p>".htmlspecialchars($row['content'])."<p>";
    echo "<small>Scris de: ".htmlspecialchars($row['name'])." (".htmlspecialchars($row['email']).") la ".$row['created_at']."</small>";
    echo " <a href='?delete_post=".$row['id']."' onclick='return confirm(\"Sigur vrei să ștergi?\")'>🗑️ Șterge</a><hr>";
}
?>
<style>
form { margin-bottom: 1rem; padding: 0.5rem; border: 1px solid #ccc; border-radius: 5px; }
input, select, textarea { margin: 0.25rem 0; padding: 0.25rem; width: 100%; }
button { margin-top: 0.25rem; padding: 0.5rem 1rem; cursor: pointer; }
table { border-collapse: collapse; margin-top: 1rem; width: 100%; }
th, td { border: 1px solid #ccc; padding: 0.5rem; text-align: left; }
h3.subtitle { margin-top: 1.5rem; }
</style>

🧠 Quiz - PHP & MySQL: Baze de date

Top