5. diel - Práca s MySQL v PHP - PDO objektovo a modulárne
V predchádzajúcom článku http://www.itnetwork.cz/...ovladace-pdo som napísal, že by bolo vhodné oddeliť prácu s databázou do samostatnej triedy, aby sme s ňou mohli pracovať na viacerých miestach - nielen v triede Adresar a nemuseli ju zakaždým znova otvárať. Otváranie databázy je totiž časovo náročná operácia. Preto ju v aplikácii otvoríme len raz a použijeme všade, kde sa nám bude hodiť.
Tentokrát už bude meno triedy mydb na mieste. Vytvoril som vlastné jednoduchú nadstavbu databázy.
<?php // soubor MyDB.class.php class MyDB{ private $spojeni; function __construct($host,$user,$pass,$name){ $options=array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8" ); $this->spojeni= @new PDO("mysql:host=$host;dbname=$name",$user,$pass,$options); } function query($query,$param=Array()){ $navrat=$this->spojeni->prepare($query); $navrat->execute($param); return $navrat->rowCount(); } function queryOne($query,$param=Array()){ $navrat=$this->spojeni->prepare($query); $navrat->execute($param); return $navrat->fetch(PDO::FETCH_ASSOC); } function queryAll($query,$param=Array()){ $navrat=$this->spojeni->prepare($query); $navrat->execute($param); return $navrat->fetchAll(PDO::FETCH_ASSOC); } }
Ako je vidieť, okrem otvorenia databázy som si vyrobil 3 metódy:
query()
, ktorá vracia len počet ovplyvnených riadkov v DBqueryOne()
, ktorá vracia prvý záznam, na ktorý narazíqueryAll()
, ktorá vracia kompletné výsledok dotazu
V mojej aplikácii síce budem potrebovať len jednu z nich, ale tie zvyšné sa nám iste budú hodiť v niektorom z ďalších pokračovaní tohto seriálu. Ak by niekomu nejaká metóda chýbala, môže si ju dopísať. Chýba tu napríklad iterátor pre vyberanie výsledkov dotazu. Ak však nepotrebujeme získavať z tabuľky státisíce riadok, chýbať nám nebude.
Prvým parametrom je SQL dotaz. Druhý parameter je nepovinný a slúži na
odovzdávanie dát pomocou tzv. Parametrizovaných otázok. Je to vynikajúca
vlastnosť ovládačov MySQLi a PDO. Pôvodný ovládač túto vlastnosť nemá,
preto je nutné dáta od užívateľov ošetriť funkcií
mysql_real_escape_string()
. PDO túto barličku nepotrebuje, dáta
je možné odovzdávať priamo. Nespornou výhodou je, že dĺžka vkladaných
dát sa nezapočítava do limitu dĺžky SQL dotazu. To iste ocenia najmä tí,
ktorí radi do databázy ukladajú fotky či videá. V našom príklade druhý
parameter zatiaľ nebude použitý.
<?php // soubor Adresar.class.php class Adresar{ private $seznam; function __construct($spojeni){ $this->seznam=$spojeni->queryAll("SELECT * FROM adresar"); if(!sizeof($this->seznam)) { throw new Exception("Tabulka je prázdná"); } } function __toString() { $headers='<tr><th>'.implode('</th><th>',array_keys($this->seznam[0])).'</th></tr>'; $rows=array(); foreach($this->seznam as $row){ $rows[]='<tr><td>'.implode('</td><td>',array_map('htmlspecialchars',$row)).'</td></tr>'; } $table=implode("\n",$rows); return <<<EOT <table border="1"> $headers $table </table> EOT; } }
Trieda Adresar doznala len kozmetické zmeny. Zjednodušil sa konštruktor a volanie SQL dotazu. Presenter je stále rovnaký.
Zostáva už len hlavný modul, ktorý nazvem jednoducho
index.php
. Musím mu nejako vysvetliť, aby si natiahol potrebné
moduly a pracoval s nimi. K tomu slúži príkaz include()
:
include('MyDB.class.php'); include('Adresar.class.php');
Lenže dnes už sa to tak nerobí, pretože u väčších projektov by mohlo
byť dosť pracné a neprehľadné starať sa o natiahnutie všetkých modulov.
Našťastie si môžeme v PHP nadefinovať funkcii so špeciálnym názvom
__autoload()
, ktorá to urobí za nás zakaždým, keď budeme
chcieť nejakú triedu použiť.
<?php // soubor index.php function __autoload($class){ include($class.'.class.php'); } try{ $spojeni=new MyDB("localhost","kit","","test"); $adresar=new Adresar($spojeni); echo $adresar; } catch(Exception $e) { echo "Tabulku nelze vypsat<br />\n"; echo $e->getMessage(),"\n"; }
Teraz je už aplikácia hotová. Je síce trochu dlhšie, než bola pôvodne, ale získali sme modulárnosť. Databázu môžeme použiť aj na iný účel so zjednodušeným ovládaním. Triede Adresár môžeme podstrčiť inú databázu alebo iný zdroj dát. Ak budeme potrebovať inú vlastnosť databázy, jednoducho ju do triedy pridáme ako ďalšiu metódu.
Javí sa niekomu výsledný kód príliš komplikovaný? Aj to je možné. Úplne prvý príklad robil prakticky to isté a mal len 14 riadok. Lenže vypísanie tabuľky je veľmi primitívne úloha. U bežných aplikácií by sme veľmi rýchlo stratili prehľad a zhoršila by sa udržiavateľnosť kódu.
Nabudúce si urobíme trochu zložitejšie príklad a vysvetlíme si záhadnú skratku CRUD.