Rozšíření pro NotORM

Školení, která pořádám

NotORM se výborně hodí pro pohodlné sestavování dotazů pokládaných do databáze, obzvlášť pokud potřebujeme pracovat se vztahy mezi tabulkami. Pokud je ale databáze navržena nešikovně nebo je příliš komplexní, tak by se hodilo nad nízkoúrovňovými funkcemi NotORM vytvořit ještě jednu vrstvu abstrakce.

Vezměme si třeba takové vícejazyčné záznamy. Pokud překlady uchováváme v samostatné tabulce, můžeme je pomocí NotORM získat následujícím kódem:

<?php
// zjištění názvu a ceny produktu v dané skupině
foreach ($notORM->product("group_id", $group) as $product) {
    foreach ($product->product_translation("language_id", $lang) as $product_translation) {
        $product_translation["name"];
    }
    $product["price"];
}
?>

Kód je sice mnohem jednodušší, než při použití nízkoúrovňových funkcí, pořád je ale dost krkolomný. A to ani nezohledňuje případ, že by překlad neexistoval. Představa, že bych musel tento kód psát při každém získání přeloženého textu, mě zrovna neláká.

NotORM proto nyní (zatím pouze ve vývojové verzi) umožňuje určit třídu, ze které se budou vytvářet vracené řádky a která může chování upravovat. Třeba takhle:

<?php
class NotORM_Row_Lang extends NotORM_Row {
    static $lang = "cs";
    
    function offsetExists($offset) {
        if (substr($offset, -1) == "_") {
            $table = $this->result->table . "_translation";
            // pokud by překlad neexistoval, vrátíme anglickou verzi
            foreach ($this->$table("language_id", array(self::$lang, "en"))->order("language_id = 'en'")->limit(1) as $row) {
                foreach ($row as $key => $val) {
                    $this->row[$key . "_"] = $val;
                }
            }
        }
        return parent::offsetExists($offset);
    }
    
    function offsetGet($offset) {
        $this->offsetExists($offset);
        return parent::offsetGet($offset);
    }
    
}
?>

Pro zjištění názvu a ceny výrobku pak lze psát skoro stejný kód, jako kdyby žádné překlady vůbec neexistovaly:

<?php
// zjištění názvu a ceny produktu v dané skupině
foreach ($notORM->product("group_id", $group) as $product) {
    $product["name_"];
    $product["price"];
}
?>

Stejně jako bez rozšíření se položí pouze konstantní počet dotazů (v tomto případě dva).

Vracená třída se dá v současné době určit pouze globálně pro objekt třídy NotORM, nicméně zvažuji, že by šla určit i pro každý výsledek zvlášť. Sám bych pro to ale asi neměl využití.

Jakub Vrána, Seznámení s oblastí, 4.8.2010, diskuse: 7 (nové: 0)

Diskuse

Martin:

Já doporučuji jako abstrakci EzSQL + šablonovací systém Smarty (http://www.learnwake.com/scripts/ez_sql/e…_smarty.html). Je to úplný ideál abstrakce, EzSQL nahází veškerý výsledek dotazu do objektu, ten je předán jako parametr šablonovacímu systému a pracuje s tím potom přitom přímo šablona.

Co se týká přehlednosti kódu, tak tohle je doslova zázrak.

eee:

Smarty (aspon co do verze 2.X) je dost stupidni sablonovaci system a k prehlednosti ma dost daleko (kdyz se snazite udelat netrivialni vec).

Pitrsonek:

Tak to s vámi nemohu souhlasit, dle mého názoru i když jsou nové šablonovací systémy Smarty je přehledné a dopře použitelné.

Nebo jaké netriviální věci máte na mysli?
Díky

MaReK Olšavský:

Obojí je ověřené, v jisté době jsem Smarty zavrhl, abych se k nim zase vrátil, protože jsem přišel k projektu, který bych už v reálném čase nepřepsal bez Smarty. Není to zrovna žádný rychlík a nejsou nejpřehlednější, bohužel s rostoucími zkušenostmi začíná být přítěží to, co mi kdysi pomáhalo, takže bude 2. pokus o desmartizaci.
EzSQL je docela bomba, byť už jsem také narazil na limity. Například vybrat data pro vygenerování XML služby zbozi.cz je s EzSQL nemozne, narazite na limit pameti pri vytvareni pole objektu/2D_Assoc_pole.
Kdysi jsem o obou knihovnách psal, ale to se mrkněte na LinuxSoft.cz.
Ad puvodni tema: Diky Jakube za tip k prostudovani.

Marek:

Ešte raz ďakujem za toto rozšírenie;-) Viem si predstaviť využitie nastavenia vrátenej triedy pre každý dotaz. Potom by sa dalo postaviť ORM nad NotORM, čo by bolo celkom vtipné ;-)
V tých triedach by sa mohli napr. definovať nejaké zložitejšie getery a setery. Dá sa to síce robiť aj teraz cez helpery priamov v šablone, ale niekto má radšej modely.

Petr Ogurčák:

Kdy nastavujete statickou proměnnou $lang? .. instance Row_Lang se vytváří až ve třídě Result.

ikona Jakub Vrána OpenID:

Vzhledem k tomu, že je statická, tak se může nastavit kdekoliv, třeba hned po připojení nebo i předním.

Vložit komentář

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL:

avatar © 2005-2018 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.