Načrtovanje in razvoj spletnih aplikacij

Zadnji ID tabele podatkovne zbirke

Po vstavljanju novega zapisa v tabelo je pogosto koristno, da izvemo, kateri identifikator je bil dodeljen novemu zapisu. To je posebej uporabno pri tabelah, kjer je glavni ključ nastavljen z AUTO_INCREMENT.

V aplikaciji Knjige se po uspešnem vnosu nove knjige uporabniku lahko prikaže tudi ID dodanega zapisa. Tako je jasno, da je bil zapis res shranjen in kateri zapis je bil ustvarjen.

Pomni: Zadnji ID lahko pridobimo šele po uspešno izvedenem ukazu INSERT INTO. Če vstavljanje ni uspelo, tudi novega identifikatorja ni.

Pri mysqli zadnji ID pridobimo s funkcijo mysqli_insert_id(), pri PDO pa z metodo lastInsertId().

Vsebina strani

Osnovna pravila

Zadnji ID je identifikator zadnjega zapisa, ki je bil dodan v tabelo prek trenutne povezave s podatkovno bazo. Najpogosteje ga uporabljamo pri tabelah, kjer se glavni ključ samodejno povečuje.

  • Tabela mora imeti stolpec z lastnostjo AUTO_INCREMENT.
  • Najprej izvedemo ukaz INSERT INTO.
  • Zadnji ID pridobimo šele po uspešnem vstavljanju.
  • Pri mysqli uporabimo mysqli_insert_id($connection).
  • Pri PDO uporabimo $pdo->lastInsertId().
  • Pridobljeni ID se nanaša na trenutno povezavo s podatkovno bazo.
  • Pri vstavljanju podatkov iz obrazca uporabimo pripravljene stavke.

Pozor: Zadnjega ID-ja ne pridobivamo z dodatno poizvedbo, kot je SELECT MAX(ID_knjige). Tak pristop je nezanesljiv, ker lahko medtem drug uporabnik vstavi nov zapis.

Vstavljanje zapisa in zadnji ID

Ko v tabelo dodamo nov zapis, podatkovna zbirka pri stolpcu AUTO_INCREMENT samodejno določi naslednjo prosto vrednost identifikatorja.

Osnovna sintaksa za vnos zapisa je:

INSERT INTO imeTabele (stolpec1, stolpec2, stolpec3)
VALUES (vrednost1, vrednost2, vrednost3);

Primer vstavljanja nove knjige:

INSERT INTO knjige
(Priimek_avtorja, Ime_avtorja, Naslov, Strani, Cena, Leto)
VALUES
('Novak', 'Janez', 'Osnove podatkovnih baz', 220, 24.90, 2024);

Po uspešno izvedenem vstavljanju lahko v PHP pridobimo ID zadnjega vstavljenega zapisa. Tako lahko uporabniku izpišemo, kateri zapis je bil dodan, ali pa ta ID uporabimo v nadaljnji obdelavi.

Pomni: Lastnost AUTO_INCREMENT se običajno uporablja pri glavnem ključu, na primer pri stolpcu ID_knjige.

Osnovni primer z mysqli

Spodnji zgled vstavi nov zapis v tabelo knjige in nato pridobi ID zadnjega vstavljenega zapisa z uporabo mysqli_insert_id().

<?php
define('DB_SERVER', 'localhost');
define('DB_USER', 'uporabnik');
define('DB_PASS', 'skritoGeslo');
define('DB_NAME', 'knjiznica');

// Povezava do podatkovne zbirke
$connection = mysqli_connect(DB_SERVER, DB_USER, DB_PASS, DB_NAME);

// Preverjanje povezave
if (!$connection) {
    die(
        'Povezava s podatkovno zbirko ni vzpostavljena: ' .
        mysqli_connect_error() .
        ' (' . mysqli_connect_errno() . ')'
    );
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $priimek = trim($_POST['priimek'] ?? '');
    $ime = trim($_POST['ime'] ?? '');
    $naslov = trim($_POST['naslov'] ?? '');
    $strani = (int)($_POST['strani'] ?? 0);
    $cena = (float)($_POST['cena'] ?? 0);
    $leto = (int)($_POST['leto'] ?? 0);

    $stmt = mysqli_prepare(
        $connection,
        "INSERT INTO knjige
        (Priimek_avtorja, Ime_avtorja, Naslov, Strani, Cena, Leto)
        VALUES (?, ?, ?, ?, ?, ?)"
    );

    mysqli_stmt_bind_param($stmt, 'sssidi', $priimek, $ime, $naslov, $strani, $cena, $leto);

    if (mysqli_stmt_execute($stmt)) {
        $lastId = mysqli_insert_id($connection);
        echo 'Zapis je bil uspešno dodan. Zadnji ID je: ' . $lastId;
    } else {
        echo 'Napaka pri vstavljanju zapisa.';
    }

    mysqli_stmt_close($stmt);
}

mysqli_close($connection);
?>

Pri mysqli je pomembno, da funkciji mysqli_insert_id() posredujemo isto povezavo, prek katere smo izvedli vstavljanje zapisa.

Osnovni primer s PDO

Tudi z vmesnikom PDO lahko po uspešnem vstavljanju novega zapisa pridobimo zadnji ID z metodo lastInsertId().

<?php
$streznik = 'localhost';
$baza = 'knjiznica';
$uporabnik = 'uporabnik';
$geslo = 'skritoGeslo';

try {
    $pdo = new PDO("mysql:host=$streznik;dbname=$baza;charset=utf8mb4", $uporabnik, $geslo);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $priimek = trim($_POST['priimek'] ?? '');
        $ime = trim($_POST['ime'] ?? '');
        $naslov = trim($_POST['naslov'] ?? '');
        $strani = (int)($_POST['strani'] ?? 0);
        $cena = (float)($_POST['cena'] ?? 0);
        $leto = (int)($_POST['leto'] ?? 0);

        $stmt = $pdo->prepare(
            "INSERT INTO knjige
            (Priimek_avtorja, Ime_avtorja, Naslov, Strani, Cena, Leto)
            VALUES
            (:priimek, :ime, :naslov, :strani, :cena, :leto)"
        );

        $stmt->bindValue(':priimek', $priimek, PDO::PARAM_STR);
        $stmt->bindValue(':ime', $ime, PDO::PARAM_STR);
        $stmt->bindValue(':naslov', $naslov, PDO::PARAM_STR);
        $stmt->bindValue(':strani', $strani, PDO::PARAM_INT);
        $stmt->bindValue(':cena', number_format($cena, 2, '.', ''), PDO::PARAM_STR);
        $stmt->bindValue(':leto', $leto, PDO::PARAM_INT);

        $stmt->execute();

        $lastId = $pdo->lastInsertId();
        echo 'Zapis je bil uspešno dodan. Zadnji ID je: ' . $lastId;
    }
}
catch (PDOException $e) {
    echo 'Napaka pri vstavljanju zapisa: ' . $e->getMessage();
}
?>

Pri PDO metodo lastInsertId() pokličemo po uspešnem klicu metode execute(). Če vstavljanje ni bilo izvedeno, zadnji ID ni zanesljiv podatek.

Preverjanje podatkov pred vstavljanjem

Tudi pri tej vrsti vnosa moramo podatke najprej preveriti. Posebej pomembno je, da so besedilna polja izpolnjena in da imajo številčna polja veljavne vrednosti.

Podatek Preverjanje
Priimek_avtorja Vrednost naj ne bo prazna.
Ime_avtorja Vrednost naj ne bo prazna.
Naslov Vrednost naj ne bo prazna.
Strani Vrednost naj bo pozitivno celo število.
Cena Vrednost naj bo število, večje ali enako 0.
Leto Vrednost naj bo smiselno celo število.

Pozor: Zadnji ID naj se uporabniku prikaže samo po uspešnem vnosu. Če ima obrazec napake, je najprej treba prikazati napake in vnos ustaviti.

Kdaj uporabimo zadnji ID

Zadnji ID je uporaben v več primerih. Pogosto ga uporabimo takoj po vnosu, ko želimo nadaljevati delo z ravnokar dodanim zapisom.

  • za prikaz potrditvenega sporočila po vnosu,
  • za prikaz podrobnosti novo dodanega zapisa,
  • za preusmeritev na stran, kot je podrobnosti.php?id=...,
  • za dodajanje povezanih zapisov v drugo tabelo,
  • za zapis dnevnika dogodkov ali obvestila uporabniku.
$lastId = $pdo->lastInsertId();
header('Location: podrobnosti.php?id=' . urlencode($lastId));
exit;

Pomni: Pri povezovanju več tabel je zadnji ID pogosto potreben zato, da povezani zapis v drugi tabeli dobi pravilen tuji ključ.

Primerjava pristopov mysqli in PDO

Oba pristopa omogočata vstavljanje zapisa in pridobivanje zadnjega samodejno dodeljenega identifikatorja.

Korak mysqli PDO
Priprava stavka mysqli_prepare() $pdo->prepare()
Vezava vrednosti mysqli_stmt_bind_param() $stmt->bindValue()
Izvedba vnosa mysqli_stmt_execute() $stmt->execute()
Pridobitev zadnjega ID-ja mysqli_insert_id($connection) $pdo->lastInsertId()
Obravnava napak Preverjanje rezultata izvedbe. Pogosto z izjemami try in catch.

Aplikacija Knjige

📘Aplikacija Knjige

V priloženi aplikaciji Knjige je rešitev razdeljena na dve datoteki. Datoteka 12_lastID-obrazec.php pripravi obrazec za vnos nove knjige in vanj doda tudi CSRF žeton. Polja obrazca so priimek, ime, naslov, strani, cena in leto izida.

Datoteka 12_lastID.php preveri metodo POST, veljavnost CSRF žetona in pravilnost vseh vnesenih podatkov. Nato izvede pripravljen stavek PDO z ukazom INSERT INTO knjige ....

Po uspešnem vnosu aplikacija pridobi ID zadnjega dodanega zapisa z metodo lastInsertId(), izpiše potrditveno sporočilo in nato prikaže še posodobljen seznam vseh zapisov.

Primer: aplikacija Knjige – 12_lastID-obrazec.php
Primer: aplikacija Knjige – 12_lastID.php
  1. Najprej pripravimo obrazec za vnos novega zapisa.
  2. V obrazec dodamo vsa potrebna polja in CSRF žeton.
  3. Ob oddaji obrazca v PHP preverimo metodo pošiljanja in veljavnost žetona.
  4. Vnesene podatke očistimo in validiramo.
  5. Za shranjevanje uporabimo pripravljen stavek INSERT INTO.
  6. Po uspešnem vnosu pridobimo zadnji ID z metodo lastInsertId() oziroma z ustrezno funkcijo v mysqli.
  7. Uporabniku prikažemo potrditveno sporočilo, zadnji ID in posodobljen seznam vseh zapisov.

Pozor: Če aplikacija po vnosu uporablja preusmeritev, pred funkcijo header() ne sme biti izpisa v brskalnik. Sicer preusmeritev morda ne bo delovala.

Priporočila

  • Zadnji ID pridobi takoj po uspešnem vnosu zapisa.
  • Uporabi isto povezavo, prek katere je bil izveden ukaz INSERT INTO.
  • Pri PDO uporabi lastInsertId().
  • Pri mysqli uporabi mysqli_insert_id().
  • Za vnos podatkov uporabi pripravljen stavek.
  • Pred vnosom preveri podatke iz obrazca in CSRF žeton.
  • Ne uporabljaj SELECT MAX(...) za pridobivanje zadnjega ID-ja.
  • Po vnosu uporabniku prikaži jasno potrditveno sporočilo.

Pogoste napake

  • Zadnji ID se bere pred izvedbo ukaza INSERT INTO.
  • Zadnji ID se bere tudi po neuspešnem vnosu.
  • Namesto lastInsertId() ali mysqli_insert_id() se uporablja SELECT MAX(ID_knjige).
  • Vstavljanje podatkov se izvede brez pripravljenega stavka.
  • Podatki iz obrazca niso preverjeni.
  • Obrazec nima CSRF zaščite.
  • Pri prikazu zadnjega ID-ja ni preverjeno, ali je bil vnos res uspešen.
  • Pri preusmeritvi po vnosu je pred header() že izveden izpis.

Zadnji ID je vezan na zadnje uspešno vstavljanje prek trenutne povezave. Zato je pomembno, da ga pridobimo takoj po izvedbi ukaza in pred drugimi postopki, ki bi lahko spremenili pomen tega podatka.