jakou použít databázovou vrstvu

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Filip111
Člen | 244
+
0
-

Ahoj, chtěl bych požádat o radu – chystám se začít s Nette, už měsíce pokukuji po vývoji FW, pročítám příležitostně diskusi a čas od času zkusím něco v sandboxu.

Teď bych chtěl zkusit přepsat alespoň frontend jednoho projektu do Nette a řeším jakou DB vrstvu použít. V diskusích je toho spousta o dibi, notORM, Doctrine a občas Nette/Database.

Je něco co byste z toho doporučili začínajícímu člověku v Nette, který doposud psal vesměs surové SQL přes ADODB?

Docela mě zaujalo Nette/Database protože to vypadá jako nativní součást Nette, ale paradoxně je v diskuzích nejméně zmiňované.

Díky, Filip

Droid
Člen | 92
+
0
-

Z osobní zkušenosti bych se Nette\DB vyhnul a bral Dibi. Až ti to přestane stačit, tak Doctrine.

arron
Člen | 464
+
0
-

Cau,

no pokud jsi nidky nic takoveho nepouzival, tak podle meho nazoru pro Tebe bude nejjednoduzsi vyzkouset dibi, ktere je opravdu velmi primocare a dost jednoduse se da implementovat prave do aplikaci, kde se to hemzi mysql_query a da se zacit pouzivat v podstate uplne stejne.

nanuqcz
Člen | 822
+
0
-

Ahoj, já doporučuju Dibi, začínal jsem na ní a zatím jsem neměl důvod ani chuť od ní odejít jinam.

Nette\Database moc nedoporučuju, je na něm ještě pořád dost práce a dotazy na fóru často končí větou „Toto zatím v Nette\Database není implementováno“.

Droid
Člen | 92
+
0
-

xxxObiWan napsal(a):

Ahoj, já doporučuju Dibi, začínal jsem na ní a zatím jsem neměl důvod ani chuť od ní odejít jinam.

Nette\Database moc nedoporučuju, je na něm ještě pořád dost práce a dotazy na fóru často končí větou „Toto zatím v Nette\Database není implementováno“.

A taky se pořád něco mění a opravuje ;-)

Filip111
Člen | 244
+
0
-

ok, Nette/Database zatím pouštím z hlavy
zkusím dibi ale ještě předtím se podívám blíž na Doctrine
(taky jsem už o tom v minulosti něco přečetl a vzhledem k tomu že přechod z vlastního php frameworku na Nette bude velký skok, nevidím důvod proč to nevzít z gruntu i u databázové vrstvy).

Díky.

na1k
Člen | 288
+
0
-

Pokud s Nette teprve začínáš, tak bych Doctrine nedoporučoval. Pokud dobře navrhneš architekturu, nebudeš mít problém později přejít, ale pro začátek si myslím že budeš mít dost co dělat s Nette, natož ještě řešit složitou db vrstvu :-)

Navíc si myslím, že pro menší věci (běžný osobní/firemní web s administrací) nemají parní mlátičky typu Doctrine cenu. Dibi je jednodušší a zřejmě i rychlejší.

Filip111
Člen | 244
+
0
-

dobře, dám na rady zkušenějších a půjdu do dibi
pravda je, že s Nette budu mít práce až kam…

Filip Procházka
Moderator | 4668
+
0
-

@**Filip111**: dibi je jednoznačně nejlepší volba pro začátečníka.

K Nette\Database jsem velice skeptický. Pokud chceš zkusit vrstvu na tomto principu, doporučuji použít NotORM, ve kterém jsou bugy opravovány v řádu hodin nebo dní, ne měsíců a nemění se ti API pod rukama. Ovšem je tu hodně vysoký WTF faktor. A to psaní dotazů může taky na pár dní zamotat hlavu.

Doctrine vyžaduje velice radikální změnu myšlení a začni po ní pokukovat, až si sám začneš říkat, že psaní SQL tě nebaví a chtělo by to něco více objektového.

@**na1k**: Doctrine není zase taková mlátička, pokud ji umíš používat efektivně :)

JakubJarabica
Gold Partner | 184
+
0
-

Súhlas. Mnoho projektov mám v Dibi – je to super, ale ako lokaj píšem mnoho SQL(DibiFluent), skúšal som aj NotORM(jednoznačne voči Nette\DB, ktoré som zatiaľ stále nepochopil :/) a pomaly sa preorientovávam na Doctrinu.

joe
Člen | 313
+
0
-

Rád bych se zeptal, jak řešíte s dibi metody v modelu… Souvisí to s databázovou vrstvou, proto se ptám přímo tady a může to i samotnému zakladateli pomoci, protože většina napsala, že používá právě dibi.

Vezmu příklad, e-shop, jak vybrat produkty?

Napíšu si metodu getAll v modelu ProductModel:

public function getAll() {
  try {
    return dibi::query('SELECT * FROM [product]');
  } catch(\DibiException $e) {
    // tady vracite svou vyjimku nebo si vystacite s tou od dibi? a nebo je odchytavate az v Presenteru a nebo vubec?
  }
}

A co teď, když budete chtít vybrat omezené množství? Přidáte metodě parametry $limit a $offset nebo si napíšete jinou? Co když budete chtít spolu s produktem vybrat i informaci o kategorii, kde se nachází (JOIN na tabulku s kategoriema)? Další metoda nebo upravujete pořád tu jednu?

Neposkytnul by mi někdo nějakou ukázku svých modelů? :-) Rád bych si v tomhle udělal nějak pořádek a nějak to sjednotil.

Pokud se používá Doctrine, tam asi takový problém právě nebude, teda myslím, že tam to funguje tak nějak „samo“ s použitím fluent interface.

Editoval joe (8. 8. 2011 22:48)

Filip111
Člen | 244
+
0
-

Dobrá otázka, snad někdo odpoví.
Musim se ale vybrečet – teď jsem skoro 2 hodiny hledal na foru jak se s dibi připojit do databáze. Návodů jsem našel dost, ale aby tam byla konfigurace s neonem a načtení konfigurace bez Enviroment…takových příkladů je tu jak šafránu.

Takže k tomu blogu za 19 minut…tehle řádek kódu byl něco přes 60 minut:

dibi::connect($container->params['database']);
Patrik Votoček
Člen | 2221
+
0
-

joe napsal(a):

Rád bych se zeptal, jak řešíte s dibi metody v modelu… Souvisí to s databázovou vrstvou, proto se ptám přímo tady a může to i samotnému zakladateli pomoci, protože většina napsala, že používá právě dibi.

V Doctrine se k tomu to účelu používá Repository kde se právě píší tyto specifické metody pro různé filtry. Pokud se nejedná o metodu findOneXxx tak se hodí přidávat parametry limit a offset.

A co se týká vyjímek měl by to obstarávat nějaky mapper (v jednodušších konstrukcích by to řešil BaseModel).

Ale hlavně bych se vyhnul volání dibi::foo protože tu máme krásné DI.

Takže u mě by ProductModel vypadal asi takto:

namespace App\Model;

class BaseModel
{
	protected $connection;

	public function __construct(\DibiConnection $connection);

	protected function query($sql)
	{
		try {
			return $this->connection->query($sql);
		} catch (\DibiException $e) {
			if (....) {
				throw new DuplicateEntryException(...);
			} elseif (...) {
				// ...
			} else {
				throw new Excetption;
			}
		}
	}
}

class ProductModel extends BaseModel
{
	public function findAll($limit = NULL, $offset = NULL)
	{
		if ($limit) {
			return $this->query("SELECT * FROM [product] LIMIT ...");
		}
		return $this->query("SELECT * FROM [product]");
	}
}
Filip Procházka
Moderator | 4668
+
0
-

@**joe**: Čtení na dobrou noc https://pla.nette.org/…itory-mapper :)

@**Filip111**: Zase špatně! :))

do configu

database:
	username: root
	password: foo
	driver: mysqli
	lazy: TRUE

services:
	db:
		class: DibiConnection
		arguments: ['%database%']

V presenteru

$result = $this->context->db->query('SELECT * FROM table');
foreach ($result as $row) {...

nebo

$query = $this->context->db->select('*')->from('table');
foreach ($query as $row) {...

Editoval HosipLan (9. 8. 2011 8:52)

Filip111
Člen | 244
+
0
-

Já to mam špatně? Jaká je výhoda použití services? (resp. nemáte nějaký odkaz, kde je to trochu vysvětlený – v dokumentaci ani na foru jsem to nijak blíž rozepsaný nenašel a zatím nechápu jejich smysl).

Mám to teď takhle:

common:
	database:
		driver = mysql
		lazy = TRUE
		charset = utf8
development < common:
	database:
		database: misa
		host: localhost
		username: root
		password:
		profiler: true
<?php
$configurator = new Nette\Configurator;
$configurator->container->params += $params;
$configurator->container->params['tempDir'] = __DIR__ . '/../temp';
$container = $configurator->loadConfig(__DIR__ . '/config.neon');

dibi::connect($container->params['database']);
?>

a v modelu pak

<?php
dibi::query('SELECT * FROM [v_content] WHERE [id] = %i', $id);
?>

Co je na tom tak špatnýho? Já tam vidím jen jednu výhodu pro můj zápis…je to kratší.
Díky.

Filip Procházka
Moderator | 4668
+
0
-

Samozřejmě máš nespornou výhodu, že je to kratší. V dokumentaci jsi evidentně špatně hledal.

Nastuduj si seriál na Zrojáku Jak na Dependency Injection a Dependency Injection v dokumentaci

Pak se můžeme bavit o výhodách a nevýhodách ;)

Patrik Votoček
Člen | 2221
+
0
-

Filip111 napsal(a):

Co je na tom tak špatnýho? Já tam vidím jen jednu výhodu pro můj zápis…je to kratší.
Díky.

Na tu první výhodu narazíš když budeš potřebovat více jak jedno spojení do DB. Na druhou až budeš psát testy.

Filip111
Člen | 244
+
0
-

Pročetl jsem něco o DI – začínám tušit, neříkám, že to chápu nebo dokážu používat.
Každopádně si připadam jak looser první den ve škole. Celkově komplikovanost objektů v nette, různé magické volání, abstrakce přes několik úrovní apod. mě dost frustruje :)
(a to nejsem úplnej začátečník – c, delphi, php, sql dělam asi už deset let, v poslední době i abap)

Budu holt dál po večerech číst a psát a snad se to v tý hlavě časem nějak pospojuje…
Díky.

o5
Člen | 416
+
0
-

Pouzivate nekdo CRUD model pres DI? Zajimalo by me, jak vam funguje napovidani IDE anebo jste se ho vzdali?

Filip Procházka
Moderator | 4668
+
0
-

Napovídání mi funguje perfektně. Protože mám vypsané služby u Containeru a pak u presenteru překryté napovídání contextu

o5
Člen | 416
+
0
-

HosipLan: Dik! To vypada funkcne.

arron
Člen | 464
+
0
-

Filip111 napsal(a):

Pročetl jsem něco o DI – začínám tušit, neříkám, že to chápu nebo dokážu používat.
Každopádně si připadam jak looser první den ve škole. Celkově komplikovanost objektů v nette, různé magické volání, abstrakce přes několik úrovní apod. mě dost frustruje :)
(a to nejsem úplnej začátečník – c, delphi, php, sql dělam asi už deset let, v poslední době i abap)

Budu holt dál po večerech číst a psát a snad se to v tý hlavě časem nějak pospojuje…
Díky.

Mival jsem v zacatcich podobne problemy, ale je to jenom o tom se toho nebat. Kdyz se trochu ponoris do zdrojoveho kodu, tak zjistis, ze je to vetsinou velmi jednoduche, jenom clovek musi mit otevrenou mysl a ne blok z toho, ze je to urcite hrozne slozity:-)

Nox
Člen | 378
+
0
-

Filip111 napsal(a):

Pročetl jsem něco o DI – začínám tušit, neříkám, že to chápu nebo dokážu používat.
Každopádně si připadam jak looser první den ve škole. Celkově komplikovanost objektů v nette, různé magické volání, abstrakce přes několik úrovní apod. mě dost frustruje :)
(a to nejsem úplnej začátečník – c, delphi, php, sql dělam asi už deset let, v poslední době i abap)

Budu holt dál po večerech číst a psát a snad se to v tý hlavě časem nějak pospojuje…
Díky.

A taky nemusíš do aktuálního projektu nacpat každou novinku nebo techniku na kterou narazíš. Že to nebude úplně puristicky dokonalé je jedno – lepší než kdybys projekt nedodělal (a magické volání by nemělo být nutné používat) a nikdo z něj tak nemohl mít užitek

Filip111
Člen | 244
+
0
-

Pravda že nemusím použít každou novinku, ale pokud nemám dostatečné znalosti současného nette a natož pak změn, které se v něm udály, blbě se rozlišuje co je důležité a co není, resp. co je správně a co špatně.

joe
Člen | 313
+
0
-

Patrik Votoček – díky za ukázku, vypadá to dobře. Osobně bych se do dalších abstrakcí nepouštěl, přijde mi to vcelku zbytečné.

Řešení filtrování, omezení (limit, offset) by bylo asi ideální řešit přes DibiFluent, ale radši mám dotazy napsané celé ručně, člověk se v nich vyzná hned a nemusí luštit, jestli se náhodou nevygeneruje trochu jiný dotaz nebo dokonce zbytečně víc dotazů, než je nutné, když by to šlo ručně spojit do jednoho – což je velká nevýhoda ORM frameworků. Aspoň v Javě jsem na to při školní práci narazil.

HosipLan – jak jsem před chviličkou napsal, nevidím důvod si ztěžovat práci takovou abstrakcí, jako jsou například entity. Nebudu z PHP dělat Javu. Asi nejsem takový objektový fanatik a programátor :), abych něco takového dělal.

Editoval joe (9. 8. 2011 21:26)

Filip Procházka
Moderator | 4668
+
0
-

@**joe**: Budu to brát jako poklonu, nerad se na někoho zlobím za hloupé urážky.

joe
Člen | 313
+
0
-

@HosipLan a jak jinak… copak bych se s tebou mohl porovnávat? Na takové úrovni nikdy nebudu, nerad ale dělám věci, co mně osobně přijdou zbytečné. S programováním jsem začal poměrně brzo (o to víc mě začíná víc a víc nudit :)), tak vím, jak se programovalo dřív. Jsem ze starý školy :) ale když mi to přijde užitečné, dokážu svoje postupy změnit hodně rychle. Vždyť víš, že jsi mi tu už několikrát pomohl a za to jsem vděčný (nejen tobě).

Filip Procházka
Moderator | 4668
+
0
-

@**joe**: Jistěže by jsi se se mnou mohl porovnávat! To ctižádost nás žene dál, nebo ne?

Co mě pobouřilo bylo slůvko fanatik :) Fanatik si nikdy nepřizná, že je fanatik a bude fanaticky bránit své názory :)

ale dost už bylo hloupostí, špiníme tu pěkné vlákno

Editoval HosipLan (10. 8. 2011 11:15)

stewe
Člen | 20
+
0
-

Nox napsal(a):
A taky nemusíš do aktuálního projektu nacpat každou novinku nebo techniku na kterou narazíš. Že to nebude úplně puristicky dokonalé je jedno – lepší než kdybys projekt nedodělal (a magické volání by nemělo být nutné používat) a nikdo z něj tak nemohl mít užitek

Presne tento pocit mam vo svojich zaciatkoch aj ja. Cokolvek spravim, vzapati zistim, ze to nemam uplne ciste a zasa to prerabam a stojim tak dlho na mieste. Riesim samotne nette viac ako projekt.

joe
Člen | 313
+
0
-

@Patrik Votoček:

Teď jsem si vzpomněl na ten tvůj ukázkový model, jak jsi sem posílal (#13). Vzhledem k tomu, že se tu poslední dobou pořád omílá DI, tak bych se ještě zeptal :)

Na dotazy to sice je dobré, máš metodu query($sql), ale co ostatní? Co transakce? Co všechny další statické metody z dibi? To bys do toho svého BaseModelu vlastně zkopíroval všechno? Nepřijde ti to trochu zbytečné, když je celkem máo pravděpodobné, že dojde k výměně knihovny dibi za jinou…? (Osobně mi to totiž přijde trochu dost nesmyslné.)

Patrik Votoček
Člen | 2221
+
0
-

Nic ti nebrání volat přímo $this->connection (statické dibi::foo(...) jsou v 99% pouze aliasy pro dibi::$connection->foo(...). V mém příkladu šlo hlavně o překlad vyjímek.

joe
Člen | 313
+
0
-

Samozřejmě máš pravdu, nevím jak jsem přemýšlel, když jsem to psal, ale snad jenom, že dibi::begin() je kratší než $this->connection->begin() :-)

Nox
Člen | 378
+
0
-

Což řeší code completition…

Patrik Votoček
Člen | 2221
+
0
-

tak si udělej alias a budeš mít $this->begin() :-D