Přejít k navigační liště

Zdroják » PHP » ORM frameworky pro PHP5: Databázový model

ORM frameworky pro PHP5: Databázový model

Články PHP, Různé

V posledním díle miniseriálu o ORM knihovnách pro PHP5 si ukážeme definici databázového modelu. Příblížíme si důvody definice pro ORM frameworky a ukážeme si nástroje pro jejich zápis. Kromě obecně známých nástrojů se seznámíme i s novým nástrojem ORM Designer, který je zaměřen na ORM frameworky a nabízí plnou podporu pro frameworky Propel a Doctrine.

Frameworky Propel a Doctrine jsou reprezentanty frameworků, které vyžadují zápis databázového modelu přímo do ORM. Toto je, společně s nutností zpracovat větší objem dokumentace, největší překážka pro vývojáře seznamující se s těmito frameworky. Než si ukážeme, jak zjednodušit vytváření databázových definic, objasníme si nejdříve důvody, proč je potřeba tyto definice vytvářet.

Jak již bylo řečeno v úvodu našeho seznámení s ORM frameworky, existují dva možné přístupy. Minimalistický, kdy framework nabízí velice lehké (z hlediska objemu kódu ORM frameworku) řešení a hlavním cílem je usnadnit základní opakující se úkony s databází. Komplexní frameworky se stávají naopak jádrem celé aplikace a nositelem větší části aplikační logiky. Aby mohl ORM framework nabídnout všechny funkce, které byly zmíněné v minulém článku, je nutné, aby znal strukturu databáze včetně relací.

Možnosti zápisu databázového modelu

Databázový model je možné definovat následujícími způsoby:

  • Objektový zápis (pouze Doctrine). V praxi se pro definici celého modelu nepoužívá. Používá se ale v zápisech šablon, které mohou doplnit sloupečky nebo tabulky pro chování. Dále je objektový zápis používán pro vytváření migrací (zápis změn databáze mezi verzemi aplikace).
  • Zápis pomocí popisného strukturovaného souboru (Doctrine i Propel). Oba frameworky umožňují zápis jak v jazyce XML tak i YAML (YAML Ain’t Markup Language – známý též z Ruby on Rails; na Zdrojáku vyšel článek YAML: Serializační formát pro ukládání dat – pozn. red.). Zápis v jazyce YAML je přehlednější a úpravy jsou efektivnější, proto se používá častěji než XML.

Níže je ukázka objektového zápisu tabulky Contact z minulého článku. Tato třída byla vygenerována automaticky z YAML zápisu. Metoda setTableDefinition obsahuje zápis sloupečků a jejich typů. Na konci metody byl ponechán zápis pro MySQL server s typem tabulky a znakové sady, který je možné pomocí Doctrine definovat. Metoda setUp nastavuje související relace. V našem případě se jedná o související záznamy z tabulky telefonních čísel (Phone). Na objektu Contact můžeme zavolat např. metodu $contact->getPhones() pro získání všech souvisejících záznamů. V metodě setUp je dále definice chování Timestampable.

/**
 * BaseContact
 *
 * This class has been auto-generated by the Doctrine ORM Framework
 *
 * @property integer $id
 * @property string $name
 * @property Doctrine_Collection $Phones
 *
 * @method integer             getId()       Returns the current record's "id" value
 * @method string              getName()     Returns the current record's "name" value
 * @method Doctrine_Collection getPhones()   Returns the current record's "Phones" collection
 * @method Contact             setId()       Sets the current record's "id" value
 * @method Contact             setName()     Sets the current record's "name" value
 * @method Contact             setPhones()   Sets the current record's "Phones" collection
 *
 */
abstract class BaseContact extends sfDoctrineRecord
{
    public function setTableDefinition()
    {
        $this->setTableName('contact');
        $this->hasColumn('id', 'integer', 4, array(
             'primary' => true,
             'type' => 'integer',
             'autoincrement' => true,
             'length' => '4',
             ));
        $this->hasColumn('name', 'string', 128, array(
             'type' => 'string',
             'length' => '128',
             ));
        $this->option('type', 'INNODB');
        $this->option('collate', 'utf8_czech_ci');
        $this->option('charset', 'utf8');
    }

    public function setUp()
    {
        parent::setUp();
        $this->hasMany('Phone as Phones', array(
             'local' => 'id',
             'foreign' => 'contact_id'));

        $this->actAs(new Doctrine_Template_Timestampable());
    }
}

Zápis stejné tabulky Contact pomocí YAML je na ukázce níže. Jazyk YAML má stromovou strukturu, pro odsazení se vždy používají 2 mezery (tabulátor je zakázaný). Pro oblíbené vývojářské nástroje již existují zásuvné moduly s podporou tohoto jazyka (např. YEdit pro Eclipse nebo Netbeans pro PHP a nebo Ruby). Editory pomohou se správným zápisem a především s kontrolou chyb, tím se vyhneme nepříjemnému hledání tabulátoru v souboru.

Contact:
  actAs: [Timestampable]
  columns:
    id:
      primary: true
      type: integer(4)
      autoincrement: true
    name:
      type: string(128)
  relations:
    Phones:
      class: Phone
      type:  many
      local: id
      foreign: contact_id

options:
  type: INNODB
  collate: utf8_czech_ci
  charset: utf8

Chcete se naučit o PHP víc?

Akademie Root.cz pořádá školení Kurz programování v PHP5. Jednodenní kurz programování v PHP 5 je určen všem webovým vývojářům, kteří se chtějí do hloubky seznámit a sžít s programovacím jazykem PHP ve verzi 5. První část kurzu je zaměřena na nový objektový model se všemi jeho vlastnostmi, ošetření chyb pomocí výjimek a efektivní využití těchto konceptů. Druhá část je zaměřena na nové knihovny PHP 5, především pro práci s databázemi, XML a objekty. Pozornost je věnována i zajištění kompatibility s PHP 4, přechodu z této verze a výhledu na PHP 6. Máte zájem o jiné školení? Napište nám!

Tvorba databázového modelu

Frameworky Doctrine i Propel obsahují skripty pro získání databázového modelu z existující databáze. Skripty fungují spolehlivě a načtou strukturu včetně relací. Tento způsob vytváření modelu je ale vhodný pouze pro vytvoření základu modelu. Ten je nutné ručně projít a doplnit nebo upravit názvy relací (příp. M:N relace), sloupce apod. U dalšího projektu většina vývojářů dá přednost ručnímu zápisu, protože již získá přehled o používaných značkách a časově jsou oba způsoby srovnatelné.

Díky popularitě modelovacího nástroje MySQL Workbench byl vytvořen zásuvný modul do této aplikace pro export do definic ORM frameworku. Kromě MySQL Workbench existují také konverzní skripty pro DBDesigner 4. Entitně relační modely (dále jen ER model) jsou nutností u aplikací využívajících relační databáze. Oceníme je zejména, když projekt vyvíjíme nebo se k projektu vracíme po delší přestávce. Bohužel exporty z modelovacích nástrojů trpí stejnými nedostatky jako zpětné získání definic z existující databáze. Proto je nutné udržovat ER model jak v modelovacím nástroji, tak i v textových definicích ORM frameworků. Modelovací nástroje neumožňují správu chování ani načtení ORM definic DB modelu, M:N relací nebo export jednoho modelu do více aplikačních modulů.

ORM designer

V říjnu 2009 byl veřejně uveden nástroj ORM Designer, který je zaměřen na ORM frameworky (v současnosti Propel a Doctrine). ORM Designer je vyvíjen českou firmou Inventic s.r.o. (autor článku je spoluzakladatelem společnosti – pozn. autora). ORM Designer obsahuje grafické rozhraní pro vytváření ER modelu stejně jako výše uvedené modelační nástroje. Navíc pak obsahuje:

  • Správu ORM atributů. Jak framework Doctrine, tak i Propel obsahují jinou sadu atributů. V případě Doctrine se jedná o definice chování, nastavení databázového stroje (viz. výše typ tabulky a kódování) atd.
  • Import a export do nativního formátu. ORM Designer umožňuje načíst model ze souborů XML nebo YAML s definicemi ORM frameworku. Dále pak upravený model do souborů zapíše v původním formátu (XML/YAML). U nového projektu stačí pouze zadat kořenovou složku a všechny definice jsou automaticky načteny, a to i z modulů.
  • Členění projektu do modulů. Databázový model je členěn do regionů a modulů. Regiony jsou pouze vizuální prvky pro sdružení souvisejících tabulek a relací. Modul je kromě vizuálního odlišení možné uložit do samostatného souboru v závislosti na příslušnosti k aplikačnímu modulu.
  • Podpora ORM frameworků. ORM Designer je postaven na pružné základně, která dovoluje použití s libovolným ORM frameworkem. Definice povolených hodnot grafického rozhraní (ORM atributy, datové typy sloupců apod.) je uložena v souborech XML. (Během prvního pololetí roku 2010 bude přidána podpora pro další ORM a MVC frameworky; v současnosti Symfony – pozn.aut.). Definice ER modelu je také uložena v souborech XML a dovoluje uživateli vytvořit konverzní skripty pro jiné frameworky nebo dokumentační systémy.

Na webu aplikace je kromě standardní dokumentace rozšiřující se seznam návodů na efektivní vývoj s ORM frameworky a frameworkem Symfony.

Shrnutí miniseriálu

V tomto miniseriálu jsme se seznámili s představiteli jednoho z možných přístupů k návrhovému vzoru Active Record. Cílem bylo přiblížit si frameworky, které jsou vzhledem ke své velikosti neprávem přehlíženy. Praktické zkušenosti z projektů ovšem ukazují, že i přes svou velikost a vyšší paměťovou a výpočetní náročnost mohou podávat srovnatelné výkony s aplikacemi psanými bez ORM frameworku. Navíc díky použití moderních programovacích technik dovolují agilní vývoj aplikací a extrémní programování. Stále ale platí, že se nejedná o jediný správný přístup a je nutné vybírat vhodná řešení pro daný projekt.

Komentáře

Subscribe
Upozornit na
guest
9 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
bezejmenný

Omlouvám se za svou neznalost, ale to co je tu popisováno je obdoba Zend_Db_Table (tedy obyčejný Active Record) nebo je to v něčem víc?

frantisek.troster

Dobrý den,

jak Doctrine tak i Propel vycházejí z návrhového vzoru Active Record, ale nabízejí mnohem více než třeba Zend_Db_Table (DQL, šablony, pluginy atd.). Viz. druhý článek:

http://zdrojak.root.cz/clanky/orm-frameworky-pro-php5-doctrine-orm/

Doctrine je také často používán se Zend Frameworkem.

Srigi

Toto je casty omyl, ku ktoremu ludia od ZF dojdu. Pravda je taka, ze Doctrine ide omnoho dalej ako Zend_Db_Table. Zend_Db_Table predstavuje iba tu najnizsiu uroven (low level) pristupu k tabulke. ORM ale dokaze abstrahovat celu biznis logiku. Ak si myslite ze trepem, skuste si to v ZF sami – clovek casto pochopi az ked uvidi/vyskusa.

Avatar

Naozaj nerozumiem tej averzii voči XML. Takmer každý editor napr. Eclipse vám pri dodanej XSD definícii dokumentu automaticky napovedá, aké vnorené elementy sa môžu vyskytovať v parent elemente. CTRL + SHIFT + F a dokument máte pekne vizuálne sformátovaný. Mne teda žiaden YAML , JSON, XYZ formát nepripadá v PRAXI ani zrozumiteľnejší, ani krajší než XML. Možno na nejaké piďi mini projektíky, ale ani futbal sa nehrá na krásu. :-)

frantisek.troster

Dobrý den,

nemám v žádném případě problém s XML. Bohužel jak pro Doctrine tak ani pro Propel nebylo v době, kdy jsem řešil volbu formátu, dostupné XSD. Navíc je to asi můj subjektivní pocit, ale konfigurace (ať už ORM nebo frameworku Symfony, který také hojně využívá YML) jsou pro mě snáze čitelné. Na druhou stranu nepopírám, že YML je snadno náchylné k překlepům. Myslím, že definice DB je už vyloženě na hraně použitelnosti YML (proto také vznikl ORM Designer).

František Kučera

„Ten je nutné ručně projít a doplnit nebo upravit názvy relací (příp. M:N relace), sloupce apod.“

Místo „relace“ by zde bylo vhodnější používat slovo „vztah“, protože pojem relace znamená v relačních databázích něco jiného. Polopaticky je to vysvětleno třeba tady: manualy.net.(bo­hužel i na české wikipedii je to špatně)

newman

Jakou mate zkusenost s vykonem Doctrine vs. Propel?
iz pomerne dlouho pouzivame Propel, ale pro jeden (vetsi) projekt jsme chteli vyzkouset Doctrine. Vsude je vychvalovan a oznacovan jako lepsi nez Propel. O rychlosti nikde zadna zminka, tak jsme to nepovazovali za velky problem (s ohledem na jeho fungovani). V realu se nam bohuzel ukazalo, ze propel je cca 5× rychlejsi nez Doctrine.

frantisek.troster

Dobrý den,

určitě mohu doporučit Doctrine. Vím, že proběhly měření rychlosti zpracování dotazu a Propel 1.3 vycházel o něco rychlejší než Doctrine. Podle mého názoru ale nezáleží na zpracování jednoduchého dotazu, protože ty aplikaci nezpomalí, největší zátěž jsou komplexní dotazy. Obrovskou výhodou jak již bylo zmíněno v článku je možnost použít v Doctrine jazyk DQL pro dotazy, je tak možné mnohem efektivněji pracovat s databází. U Propelu buďto budete bojovat s „Criteriony“ nebo použijete PDO nebo Creole, což vás ale připraví o výhody ORM (objekty, posluchače atd.).

Právě ty slepé uličky, do kterých se člověk na větších projektech s Propelem dostane, nás přesvědčily o nutnosti migrovat projekty na Doctrine. A musím říct, že i přes občasné škobrtnutí, nás co se stability a flexibility týče Doctrine nazklamala. Pokud pracujete na projektu, který má být nasazen do produkčního prostředí až za několik měsíců, zvažte zda nepoužít Doctrine 2 (momentálně alfa verze, ale již nyní použitelná pro vývoj). Dokumentace již existuje a rozrůstá se i komunita pracující s tímto frameworkem.

newman

Tak my jsme prave pouzili na jednom vetsim projektu Doctrine (kvuli podobne oslavnym clankum) a po velkem prekvapeni nad neocekavanou pomalosti systemu jsme po spouste debugovani, profilovani a logovani zjistili, ze problem je v Doctrine. Takze jsme udelali migraci na Propel, ktery pouzivame vsude jinde. V kritickych castech byl Propel i 10× rychlejsi nez Doctrine, obecne je cely system nyni 5× rychlejsi s vyrazne mensi pametovou narocnosti (2×QuadCore, 8GB pameti a pokles zatizeni z 85% na <20%). Podotykam, ze chyba nebyla ve spatne spatne nastavenem lazy nacitani objektu, ale vykon se ztracel na parsovani dql a generovani objektu.

Co se tyce propelu, tak tam zatim spokojenost. Nikdy jsme se nedostali do neresitelne situace, problematicke casti byly stejne problematicke jako v Dql (slozitejsi subselecty atd.). Creole je vec 3 roky stareho propelu 1.2 (aktualni verze 1.4.1). Na zadne jine problemy jsme nenarazili za ty roky, co jej pouzivame. Aktualne je i vyvoj velmi svizny a slibny. Jedina velka vyhoda Doctrine tedy je dokumentace, kde propel doopravdy pokulhava.

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.