Doctrine (ORM pre PHP)
Doctrine (Doktrína) je objektovo relačný mapper (ORM) pre PHP 5.2.3+, ktorá je umiestnená na databázovej vrstve (DBAL). Jedným z jej hlavných funkcií je možnosť písať databázové dotazy pomocou vlastného objektovo orientovaného SQL dialektu tzv. Doctrine Query Language (DQL), inšpirovaný známym Hibernate HQL. To poskytuje vývojárom výkonnú alternatívu k SQL, ktorá udržiava pružnosť, bez nutnosti zbytočných duplicít kódu.
Čo je vlastne ORM?
Objektovo relačné mapovanie (ORM) je technika používaná v programovacích jazykoch, ktorá rieši rôzne nekompatibilné typy dát v relačných databázach. To v podstate umožňuje, aby sme mali “virtuálnu objektovú databázu”, ktorá môže byť použitá z daného programovacieho jazyka. Existuje veľa voľných i komerčných balíkov, ktoré to ponúkajú a niektorí vývojári sa rozhodli si vytvoriť vlastné ORM.
Inštalácia doktríny
Inštalácia doktríny cez SVN je veľmi jednoduchá. V podstate nejde o inštaláciu ale o jednoduché stiahnutie. Stačí si teda stiahnuť akúkoľvek verziu doktríny z SVN servera: http://svn.doctrine-project.org
Ak chcete vyskúšať konkrétnu verziu, môžete použiť nasledujúci príkaz z terminálu:
svn co http://svn.doctrine-project.org/branches/1.2 .
Implementácia / inicializácia
Najskôr je samozrejme nutné si v php doktrínu includnúť – nastaviť cesty pomocou funkcie set_include_path(). Includuje sa nadradený adresár adresáru Doctrine (mám na mysli adresár 1.2/lib/Doctrine/). Napríklad:
/* V adresari $appFolder/library/ sa nachadza adresar Doctrine a subor Doctrine.php */ set_include_path(get_include_path() .PATH_SEPARATOR ."$appFolder/library/");
No a potom je potrebne doktrínu inicializovať. Predovšetkým je potrebné knižnici povedať kam sa budeme napájať. Napríklad:
$manager = Doctrine_Manager::getInstance(); $manager->setAttribute(Doctrine::ATTR_MODEL_LOADING, Doctrine::MODEL_LOADING_CONSERVATIVE); $manager->setAttribute(Doctrine::ATTR_AUTO_FREE_QUERY_OBJECTS, true); /* tvorba pripojenia do db */ $connection = $manager->connection( $config->databaze->stroj .'://' .$config->databaze->username .':' .$config->databaze->password .'@' .$config->databaze->host .'/' .$config->databaze->dbname, 'doctrine' ); $connection->setCharset('utf8'); $connection->setAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER, true); $connection->setAttribute(Doctrine::ATTR_VALIDATE, Doctrine::VALIDATE_ALL); $connection->setAttribute('portability', Doctrine::PORTABILITY_ALL); $connection->getDbh()->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
Vytvorenie modelov
Aby ste mohli s databázou v doktríne pracovať ostáva nám urobiť ďalší dôležitý krok. Ako to už bolo spomenuté v odseku ORM, doktrína je vlastne vrstva ktorá robí program nezávislý od konkrétneho databázového stroja. Je jedno teda, či je to Postgresql, MySQL či Oracle. Je teda potrebné vytvoriť akúsi reprezentáciu databázy. No a v doktríne s databázou manipulujem prostredníctvom modelov – tried, odvodené od Doctrine_Record. Aby sme tieto modely nemuseli vytvárať ručne, Doctrine nám ponúka metódu, ktorá nám ich vygeneruje automaticky z databázy. Samozrejme odporúčam si tieto modely následne upraviť a skrášliť a napríklad namiesto uzivatelSkupinaId používať skupina_uzivatela_id a pod. A teraz samotný kód pre vygenerovanie modelov:
Doctrine::generateModelsFromDb('models', array('doctrine'), array('generateTableClasses' => true));
Metóda GenerateModelsFromDb vyžaduje len jeden parameter, a to je importný adresár (adresár, kde budú uložené vygenerované súbory). Druhým argumentom je pole mien databázových spojení pre ktoré sa vytvoria modely, a tretím argumentom sú jednotlivé predvoľby pre tvorbu modelov.
A teraz ukážka modelu užívateľa:
abstract class BaseUzivatel extends Doctrine_Record { public function setTableDefinition() { $this->setTableName('tbl_Uzivatel'); $this->hasColumn('uzivatelId as id', 'integer', 6, array('type' => 'integer', 'primary' => true, 'autoincrement' => true, 'length' => '6')); $this->hasColumn('uzivatelMeno as uzivatelske_meno', 'string', 32, array('type' => 'string', 'default' => '', 'notnull' => true, 'notblank' => true, 'length' => '32')); $this->hasColumn('uzivatelHeslo as heslo', 'string', 255, array('type' => 'string', 'default' => '', 'notnull' => true, 'notblank' => true, 'length' => '255')); $this->hasColumn('uzivatelSkupinaId as skupina_uzivatela_id', 'integer', 5, array('type' => 'integer', 'default' => '', 'notnull' => true, 'length' => '5')); $this->hasColumn('uzivatelZmazany as zmazany', 'tinyint', 1, array('type' => 'tinyint', 'default' => '0', 'notnull' => true, 'length' => '1')); $this->hasColumn('rolaId as rola_id', 'integer', 2, array('type' => 'integer', 'default' => '1', 'notnull' => true, 'length' => '2')); } } class Uzivatel extends BaseUzivatel { }
Použitie
No a teraz poďme k nejakému príkladu. Budeme pritom pužívať vyššie uvedený model Uzivatel
Hľadám užívateľa (SELECT)
Jendoducho chceme nájsť užívateľa podľa jeho mena. A tu je kód:
$uzivatelia = Doctrine_Query::create() ->from('Uzivatel') ->where('uzivatelske_jmeno = ?', $uzivatelske_jmeno) ->execute(); foreach ($uzivatelia as $uzivatel) { if ($uzivatel instanceof Uzivatel) { echo 'Nasli sme uzivatela s menom '.$uzivatel->uzivatelske_meno; } }
Jednoduché a prehľadné však? Lenže ono to ide ešte jednoduchšie (!):
/* Tento kod vrati prveho najdeneho uzivatela s danym menom */ $uzivatel = Doctrine::getTable('Uzivatel') ->findByuzivatelske_jmeno($uzivatelske_jmeno); ->getFirst();
Vytvorenie nového užívateľa (INSERT)
$uzivatel = new Uzivatel(); $uzivatel->uzivatelske_meno = $uzivatelske_meno; $uzivatel->heslo = $heslo; $uzivatel->skupina_uzivatela_id = 8; $uzivatel->rola_id = 1; $uzivatel->save();
