Maërlyn

PDO

2011. 12. 03.

Bár a php mysql ext-je hivatalosan is deprecated, iszonyatos mennyiségű ezt használó kód, példa található, pedig régóta van két sokkal jobb alternatíva is: a mysqli és a PDO. Az utóbbiról tartanék egy gyors bevezetést.

$db = new PDO(
  "mysql:host=localhost;dbname=test",
  "root",
  "root",
  array(
    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8;',
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
  )
);

Az eddigi két függvényhívás helyett a kapcsolódás mindössze egy konstruktorhívás. Megmondjuk továbbá, hogy rögtön kapcsolódás után állítsa a kapcsolat kódolását utf8-ra, valamint php5-höz híven ha egy query hibás, dobjon egy php Exceptiont.

Lekérdezés futtatására két lehetőségünk van: a közvetlen és a prepared statementen keresztüli. Utóbbit érdemes használni, ha belekerül bármi, amit a usertől kapunk.

$stmt = $db->query("SELECT * FROM blog ORDER BY date DESC LIMIT 10;");

$stmt = $db->prepare("SELECT * FROM blog WHERE id = :id;");
$stmt->execute(array(
  ":id" =>  $_GET["id"],
));

Két sajnálatos kivétel akad: a limit és az offset paramétereit nem lehet így átadni, ott magunknak kell megoldanunk azon értékek biztonságossá tételét.

Van egy harmadik módszer is, ezt akkor érdemes használni, amikor nem várunk eredményhalmazt (mert például beállítunk valamit, vagy egy DELETE queryről van szó):

$db->exec("SET time_zone = '+01:00';");
$db->exec("DELETE FROM `blog`;);

ennek visszatérési értéke egy egész, ami a módosított sorok számát tartalmazza.

A prepared statementek hatalmas előnye a korábbi, kézzel összeállított querykkel szemben, hogy gyakorlatilag tökéletesen védve vagyunk az SQL injection támadásokkal szemben, nem fordulhat elő, hogy egy változót elfelejtünk escapelni.

Mindkét megoldás egy PDOStatement példánnyal tér vissza, aminek megvan az a csodás tulajdonsága, hogy megvalósítja a Traversable interface-t, ergo egy foreach()-csel bejárható:

foreach ($stmt as $row) {
  // feldolgozás, kiírás
}

Természetesen nem csak így lehet végigmenni az eredményhalmazon. Ott van például a fetchAll(), ami az összes kapott sort adja vissza egy tömbként.

Aztán ott a fetch(), ami a klasszikus mysql_fetch_row() megfelelője - visszaadja a következő sort, ha meg már nincs, akkor logikai hamist. Sok paramétere van, például rávehető a lazy loadingra, vagy hogy adott típusú objektumba hidrálja a következő sort.

Ami még jól jöhet: stringek query-biztossá tétele:

$id = $db->quote($_GET["id"]);