„dibi vs. Nette Database“ story
Je nejvyšší čas rozseknout FUD a nejasnosti kolem databázových vrstev.
Databázovou vrstvu dibi jsem začal psát cca před devíti lety se záměrem shrnutým v tomto historickém článku. Šlo mi především o to sjednotit API různorodých klientů, ošetřovat chybové stavy, přidat uživatelsky pohodlné bindování parametrů a také dynamické generování základních konstrukcí SQL, jako jsou například podmínky, řazení a INSERT & UPDATE:
$db = new DibiConnection(...); // or via monostate dibi::connect(...)
$pairs = $db->fetchPairs('SELECT id, name FROM countries');
$arr = array(
'name' => 'John',
'modified%d' => time(),
);
$db->query('UPDATE users SET ', $arr, ' WHERE `id`=%i', $id);
// UPDATE users SET `name`='John', `modified`= '2005-10-12' WHERE `id` = 123
Časem se v PHP objevila nativní knihovna PDO, která v podstatě řešila polovinu věcí, co dibi, nicméně její API pro bindování parametrů bylo těžkopádné, neporadilo si s datumy a skládání základních konstrukcí SQL chybělo úplně. Takže dibi nenahradilo.
V dibi jsem si hrál i s experimenty, jako DibiTable, DibiFluent nebo DibiDataSource, ale sám jsem je nikdy nepoužíval. Jsou tam pochopitelně i věci, které bych dnes udělal lépe, ale z hlediska zpětné kompatibility je takřka nemožné do nich zasahovat. Třeba mám zmatek v tom, co který modifikátor znamená – je jich příliš mnoho. (Moc se to neví, ale místo přemýšlení, který modifikátor použít, můžete obvykle použít otazník.)
Protože téměř v každém demu pro Nette bylo potřeba pracovat s databází, vyžadovalo to nainstalovat dibi nebo Doctrine (jiné vrstvy se v podstatě nepoužívají). Dnes je to díky Composeru otázka pár úderů do klávesnice, ale tehdy neexistoval. Přemýšlel jsem proto, že bych si v příkladech vystačil jen s čistým PDO. Jenže pokud jste rozmlsaní z dibi, není návratu zpět. Chybí vám nejen přívětivé API, ale i pohodlí Tracy (tj. Laděnky) pro monitorování dotazů či chyb.
Tehdy mě napadlo, že by nebylo od věci udělat „dibi model 2010“, nově, bez historických zátěží, založené čistě nad PDO. Vyhodit hromadu driverů, všechny modifikátory nahradit jedním otazníkem a implementovat jen vlastnosti, které budou skutečně potřeba.
Nette Database
Takhle vzniklo Nette Database (NDB). Moderní ekvivalent dibi:
$db = new Nette\Database\Connection(...);
$pairs = $db->fetchPairs('SELECT id, name FROM countries');
$arr = array(
'name' => 'John',
'modified' => new DateTime,
);
$db->query('UPDATE users SET ', $arr, ' WHERE `id`= ?', $id);
Brzy jsem narazil na hromadu nedostatků PDO, nareportoval a obešel mraky chyb a když bylo Nette Database odladěné, vyšlo v únoru 2012 jako součást finálního Nette Framework 2.0.
Tady musím zdůraznit, že navzdory šiřitelům FUD v Nette Database skutečně takřka žádné chyby nebyly a jediným větším problém se ukázal bug v PDO způsobující memory leaky, kvůli němuž musely být třídy NDB přepsány a v Nette 2.1 již Connection není potomkem PDO (dědit od PDO byla z dnešního pohledu stejně blbost.)
Dnes nevidím důvod, proč pro nový projekt použít staré dibi namísto NDB. Chybí asi jen:
- bohatší možnosti skládání v klauzuli WHERE (zatím se nezdá, že by byla potřeba)
- statická obálka
dibi::
(tu v Nette nahrazuje DI Container) - samostatnost (vyřeší Nette 2.2)
- fetchAssoc (tu v Nette nahrazuje NDBT,
eventuálně by ji šlo doplnitje v 2.2-dev)
A tím se dostáváme k Nette Database Table (NDBT), prapříčině mnoha zmatků.
Nette Database Table (nyní Explorer)
V prosinci 2010 jsem do tehdy beta verze Nette 2.0 začlenil knihovnu Jakuba Vrány NotORM, ve kterém jsem viděl úžasný nástroj pro dolování dat z databáze:
$pairs = $db->table('countries')->fetchPairs('id', 'name');
// SELECT `id`, `name` FROM `countries`
$name = $db->table('book')->get($id)->author->name;
// SELECT `id`, `author_id` FROM `book` WHERE `id` = 123
// SELECT `id`, `name` FROM `author` WHERE (`author`.`id` IN (456))
$arr = array(
'name' => 'John',
'modified' => new DateTime,
);
$db->table('users')->where('id', $id)->update($arr);
// UPDATE users SET `name`='John', `modified`= '2005-10-12' WHERE `id` = 123
Kód i API jsem upravil tak, aby zapadlo do koncepce Nette, v podstatě z myšlenky využít NotORM v Latte pochází i nápad na tzv. předbíhání budoucnosti, neboli načítání jen těch sloupců, které budou později potřeba, taktéž s Latte může skvěle fungovat koncept NotORM 2.
A právě NotORM v NDB nese označení NDBT (nyní Nette Database Explorer). Přičemž její použití je volitelné.
Zapojení do Nette vyvolalo o NDBT resp. NotORM velký zájem a ukázalo se, že byť byla knihovna pro potřeby Jakuba odladěná, pro různorodější požadavky bylo třeba odvést ještě hodně práce. Té se od poloviny roku 2011 ujal Hrach a z velké části původní NDBT přepsal a pečlivě doplnil testy. Knihovna procházela mnohem rychlejším vývojovým cyklem než zbytek frameworku, nicméně nebýt jeho součástí, nevyvíjí se asi vůbec.
Nette tedy má
- NDB (nyní Nette Database Core), obdobu dibi, stabilní od verze 2.0.0
- NDBT (nyní Database Explorer), obdobu NotORM, vhodnou pro produkční nasazení až od verze 2.1
Dibi nadále udržuji, koneckonců běží mi na něm většina webů, ale žádné novinky nechystám. V podstatě ani do NDB ne. Naopak s NDBT, jenž pohání mimo jiné i tento blog, má Hrach ambiciózní plány.
Aktualizace 2017: Původní Nette Database Table (NDBT) nese nový název Nette Database Explorer a samotné jádro je Nette Database Core
Komentáře
Tharos #1
Image zabugované knihovny IMHO vznikla tak, že zpočátku si pod pojmem „Nette Database“ myslím nikdo nepředstavil NDB, nýbrž rovnou celé NDB+NDBT. Myslím, že nikoho ani nenapadlo vnímat to jako dvě oddělené knihovny, tuplem pak při nalezení bugu přemýšlet o tom, jestli je to chyba v NDB nebo NDBT. Uznávám, že Ty jsi to prezentoval jako dvě „komponenty“ od samého začátku: https://forum.nette.org/…-predstaveni#…, ale hned navazující diskuze je téměř celá o NDBT.
Já projektu od začátku velmi fandím. Věřím, že už konečně jde o stabilní knihovnu a že důvody, proč jsem ji přestal po pár pokusech používat, už jsou pasé. Odvedli jste na kódu s Hrachem velký kus práce!
Taco #2
Tak já jsem přesně ten případ, který díky dojmu, že NDB a NDBT jedno jsou, celou Nette Database zavrhl, a dále používal Dibi. Díky, mrknu na to.
Jan juzna Doleček #3
Nette používám už dlouho a v jeho použití se považuji za pomněrně zkušeného. Používám i zabudovanou funkcionalitu pro přístup k databázi, dokonce jsem se snažil angažovat i v jejím vyvoji. O tom, že jde o dvě různé „komponenty“ jsem se bohužel ale dozvěděl až teď.
Docela škoda, že toto rozdělení nebylo jasně prezentováno od začátku. A nebo jsem to jen nepostřehl?
Honza T #4
NDB pořád považuji za takové osekané dibi, ve kterém nelze rozumně skládat složité dotazy. A nad NDBT neumím postavit pořádný model.
Vojtěch Semecký #5
#2 Taco, Já jsem celou Nette Database sice nezavrhl, ale že existují 2 samostatné komponenty my nějak ušlo. Fandím té NDB. NDBT asi používat nebudu. Přemýšlím v SQL a NDBT mě od něj příliš odstiňuje.
Prixa #6
Tohle jsem měl vědět dřív. A i mnozí další. Totiž i Nette guru šířili kolem sebe bludy, např. https://forum.nette.org/…stable-verzi#… (cituji: „mluvím hlavně o chybách Nette\Database.....přes jeho obrovskou snahu ta knihovna prostě není ani zdaleka tak stabilní jako dibi“)
Caine #7
Řekl bych, že jsou dva důvody, proč jsme všichni měli za to, že ndb = ndbt..
Honza T #8
#6 Prixo, Proč bludy? Tharos si pod pojmem
Nette\Database
představoval to, čemu dnes David říká NDBT (v té době to označení IMHO vůbec neexistovalo, protože ho poprvé použil Hrach před 5 měsící a odkázaný příspěvek je starý 9 měsíců), reagoval jsem tedy na dotaz ohledně NDBT. Nehledě na to, že pokud chci psát SQL dotazy ručně, tak místo NDB použiji stejně dibi, protože v NDB prostě chybí některé dost zásadní funkce.Prixa #9
#8 Honzo Te, Nějak jsem se ztratil a jako začátečník mě to dost mate. Ty použiješ dibi, protože v NDB chybí zásadní funkce? Přitom přímo v tomto článku se píše, že v NDB nic zásadního nechybí („…nevidím důvod, proč pro nový projekt použít staré dibi namísto NDB“)!
Jak to tedy je?
Honza T #10
#9 Prixo, Vždyť hned v další větě David zmiňuje některé z věcí, který chybí (je jich víc, pochopitelně). Buď je potřebuješ, nebo ne.
enumag #11
NDBT (a mimochodem tu zkratku vidím dnes poprvé) jsem používal poměrně dlouho, ale stejně jako Honzovi se mi nad tím nikdy nepodařilo napsat model se kterým bych byl spokojen, Možná to napraví Nextras/ORM i když mně už na tom po přechodu na Doctrine nesejde.
bckp #12
Mě osobně u NBD chybí právě fetchAssoc, což považuji za killer feature od Dibi a důvod, proč do dnešního dne používám právě Dibi. Bohužel mi celý koncept NotORM nesedí, rád si píšu čisté dotazy.
Možná by mohl David vydat ještě jednu verzi Dibi, kde by odebral deprecated věci, sám jsem to zkoušel ale nepovedlo se mi ji pak minimalizovat tak pěkně jako to umí právě David :(
Peggy #13
Mě docela mrzí že NDB nemá to co poskytrovalo DibiFluent .. prostě psát si vlastní SQL dotazy, ale skládat je fluentně … Přechod na Nette Database sem tudíž ještě furt nějak uplně nepřekousl :D
OnGe #14
Když bude NDB samostatná v Nette 3, v jak daleké budoucnosti Nette 3 vlastně leží?
David Grudl #15
#12 bckpe, fetchAssoc je ve 2.2-dev verzi Nette (syntax je mírně jiná než u dibi)
#13 Peggy, fluentním zápisem disponuje právě NDBT, takže by asi nemělo moc opodstatnění nějaké ND Fluent přidávat
#14 OnGe, doufám, že to bude otázka několika měsíců
Martin #16
Pochopení rozdílu nenahrává asi ani to, že v české dokumentaci je NDB přeložen jako „Databáze & ORM“, NDBT jako „Databáze & ORM“ a Table\Selection jako „Databáze & ORM“…
Pechy #17
Já jsem si na NDBT tak rychle zvykl a zakousl se do něj, že se mi absolutně příčí dělat na čemkoliv, kde není. Takže ho cpu do každého staršího projektu, na kterém dělám. Fakt super práce.
Felix #18
Na rychlé prototypování je to super. I nějaký základní model lze postavit. ORM to není, tak bych ho s tim ani nesrovnával.
Tento článek byl uzavřen. Už není možné k němu přidávat komentáře.