Nette\Database: představení

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

Aha, ok … nejak to ocuram. Dik.

PetrNovotny
Člen | 5
+
0
-

Osobně se mi moc nelíbí nazývat pilířem modelu implementaci Table a Row Gateway jakou je Nette\Database nebo notORM a demonstrovat jí na příkladech typu načtění dat z presenteru nebo přímo z view. Spoustu lidí to může naučit špatnýmu přístupu k tomu jak podobný nástroje používat..
Jinak samozřejmě dobrá práce;) Ale použití bych demonstroval asi jinak, vyloženě na načtení dat do modelu aplikace..

JJWorren
Člen | 6
+
0
-

mám stejný problém, potřeboval jsem nastavit table prefix pomocí reflection a vypadáto že ho to úplně ignoruje :-(

Michal Blaha
Člen | 2
+
0
-

Trošku se zpožděním k otázce „umí joinovat subselecty?“

vrana napsal(a):

Tak to nejde. K čemu se to hodí?

například:

SELECT * FROM car
INNER JOIN (
	SELECT * FROM event WHERE type = 5
) event ON car.id = event.car_id

je rychlejší než:

SELECT * FROM car
INNER JOIN event ON car.id = event.car_id
WHERE event.type = 5

vrana napsal(a):

Tomu se mi nechce věřit…

Pokoušel jsem se to nasimulovat a musím tě dát za pravdu.
… pošlu nějaký lepší příklad, až na něj narazím :-)

Editoval Michal Blaha (30. 4. 2011 23:59)

vrana
Člen | 131
+
0
-

Michal Blaha napsal(a):

… na MySQL tabulkách obsahujících velké množství dat (statisíce řádků) jsme tím dosáhli zkrácení času až o 75%

Tomu se mi nechce věřit. Co na to říkal EXPLAIN? Nedalo se běžnému JOINu trochu napovědět (třeba použitím LEFT JOIN s tabulkami v lepším pořadí nebo klauzulí USE INDEX)? Jak je na tom výkonnostně „nativní“ NotORM řešení?

<?php
$db->car("id", $db->event("type", 5)->select("car_id")
?>
Peter
Člen | 12
+
0
-

Jak moc je Nette\Database hotová? Tuhle David povídal cosi o tom, že to není ještě úplně ono a s případným nasazením se má ještě počkat, ale jak koukám, tak se to tu vesele používá.

Mám totiž v plánu to použít pro jeden větší projekt a nerad bych v půlce vývoje narazil na nějakou záludnou past v podobě chybějícího čehosi. Hrozí tu něco takového, nebo se případně dá zároveň s Nette\Database použít něco pod tím (PDO?) či úplně jiného (NotORM, Doctrine2)?

Honza Marek
Člen | 1664
+
0
-

Úplně hotové to rozhodně není. Rozumné je asi použít dibi, NotORM nebo Doctrine2, podle toho jaký styl práce s modelem je člověku vlastní. Jinak NotORM by měl být Nette\Database hodně podobný.

Bernard Williams
Člen | 207
+
0
-

Nazdárek,

nové databáze nepodporují dibi operátory typu %v, %a, %if, %end, %and atd? Jak se řeší dotazy s těmito operátory? Mají nějaké ekvivalenty nebo na vše stačí „?“ ?

Bernard

Filip Procházka
Moderator | 4668
+
0
-

Takové věci z principu nepotřebuješ. Použij konstrukce php

$q = $database->select...;

if ($neco) {
	$q->where(...;
}

foreach ($q as $row) {
...
Bernard Williams
Člen | 207
+
0
-

A metody typu begin(), commit(), insertId().. je potřeba si napsat sám?

Jan Voráček
Člen | 90
+
0
-

Nette\Database\Connection dědí od PDO, takže můžeš používat metody PDO – viz API. Metoda insert() pak navíc vrací ActiveRow s vloženými daty včetně vygenerovaného id.

David Grudl
Nette Core | 8082
+
0
-

Nette\Database jako náhrada za dibi by měla být plně funkční, prakticky od vydání. Integrované NotORM (řekněme náhrada za DibiFluent) ještě není finální.

Bernard Williams
Člen | 207
+
0
-

No docela se teď s Nette\Database peru.. Pak by bylo super rozšířit dokumentaci.

Jo a ještě jedna věc. Nevím, jestli je to chyba PDO nebo Nette\Database / NotORM, ale v případě, že v SQL dotazu vybírám 2× stejnou buňku (pochopitelně omylem), tak dochází k přetypování některých buňkách (zatím jsem nenašel logiku ve kterých – asi se to řídí podle pořadí/indexů) – nehodí to žádnou chybu! Když stejný SQL dotaz dám třeba do Admineru, tak to funguje správně – tj. ve výsledku se zobrazí 2× stejná buňka se stejnou hodnotou a zbytek je takový, jak má být. String se třeba změní na „TRUE“ nebo „1“, prázdný řetězec na 0 atd.. prostě chaos.

Elijen
Člen | 171
+
0
-

Jsem jediny, koho zaujalo pouziti fopen v prikladu? :)

$database->exec('INSERT INTO users', array(
        'name' => 'Jim',
        'created' => new DateTime,
        'avatar' => fopen('image.gif', 'r'), // <----- ???
));

Editoval Elijen (9. 8. 2011 15:55)

paranoiq
Člen | 392
+
0
-

David Grudl napsal(a):

jak z dané struktury vypíšu pomocí Nette Database jméno maintainera ke všem aplikacím?

hrach
Člen | 1834
+
0
-

Musíš použít DiscoveryReflection. Pak stačí

foreach  ($db->table('application') as $app) {
	echo $app->title . " - " . $app->maintainer->name;
}
Elijen
Člen | 171
+
0
-

Neslo by to i bez DiscoveryReflection pomoci metody through?

josef.sabl
Člen | 153
+
0
-

hrach napsal(a):

Musíš použít DiscoveryReflection. Pak stačí

Co je DiscoveryReflection?

paranoiq
Člen | 392
+
0
-

DiscoveryReflection zjišťuje strukturu tabulek (cizí klíče atd.) přímo z databáze a napovídá Selection/ActiveRow, kam mají pro data sahat. je pomalejší, ale funguje nezávisle na použité konvenci. (v uvedeném příkladu konvenci dodržet nelze)

Editoval paranoiq (12. 12. 2011 18:52)

josef.sabl
Člen | 153
+
0
-

paranoiq napsal(a):

DiscoveryReflection zjišťuje strukturu tabulek (cizí klíče atd.) přímo z databáze a napovídá Selection/ActiveRow, kam mají pro data sahat. je pomalejší, ale funguje nezávisle na použité konvenci. (v uvedeném příkladu konvenci dodržet nelze)

Díky za odpověď. Samozřejmě tuším, co to znamená obecně. Mně šlo ale o vazbu a použití v Nette. Jediné, co našel Google na téma Nette DiscoveryReflection kloudného je totiž tohle vlákno.

Nakonec jsem se k tomu propídil tak, že jsem objevil funkci Connection->getDatabaseReflection(), zkusil jsem ji použít, zjistil jsem, že vyšlo nový Nette a pak v config.neon jsem objevil zmínku o reflexi.

Pracovat s Nette je radost. A teď to myslím upřímně i sarkasticky zároveň, připadám si jako zlatokop :-)

paranoiq
Člen | 392
+
0
-

tak ses měl zeptat jak se to používá ;-]

josef.sabl
Člen | 153
+
0
-

paranoiq napsal(a):

tak ses měl zeptat jak se to používá ;-]

V tom kontextu jsem myslel, že to bude jasný,
ale máš pravdu, byl jsem trochu moc stručnej ;) Díky

Editoval josef.sabl (13. 12. 2011 15:03)

bojovyletoun
Člen | 667
+
0
-

Co zvážit přidání fetchAll():https://github.com/…6f153e391eaf

Jo ještě mám jeden nápad, nebo spíš, by mě zajímalo, jaké chování vám připadá normální (u případu 2)(1 fungujetak jak chci)
Co takhle upravit metodu update, aby entitě nastavila updatované hodnoty? Je to žádoucí? Myslím že by stačilo něco upravit metodu update

$task=$db->table(tasks)->get(14); //1,2,...
//1.
$task1->done = !$task->done;
$task1->update();
$task1->done nyní obshahuje aktuální hodnotu.

//2.
$task2->update(array('done' => !$task->done));
$task2->done obsahuje hodnotu před updatem.

//3.
Samozřejmě pak je tu možnost místo !$task->done použít new Literal('not done');, ale tam je evidentní, by bylo nutné po updatu data hned přečíst z db.

Zmíněná úprava

@github

Editoval bojovyletoun (28. 12. 2011 21:55)

paranoiq
Člen | 392
+
0
-

fetchAll() je antipattern. navádí k plýtvání pamětí

  1. to by chtělo
juzna.cz
Člen | 248
+
0
-

EDIT: presunuto do vlastniho vlakna

foreach ($database->table('application')->where('authorId = ?', $authorId) as $application)
{
	echo $application->title, ' (', $application->author->name, ')';

	foreach ($application->related('application_tag') as $application_tag) {
		echo $application_tag->tag->name . ', ';
	}
}

Mam prakticky stejne schema a stejny cyklus, jako bylo zmineno, ale natahuju a vypisuju treba 1–2tis polozek z application. Vnitrni cyklus pak udela SQL dotaz obsahujici 1–2tis. polozek v IN a to je strasne pomale :(
Jak takovy pripad resite vy? Kdyby bylo k dispozici fetchAssoc() tak si udelam join a rozparsuju si to do pole, ale takto jsem ztracen :(
Dik

Edit: Napadlo me udelat si k takove tabulce hint, pomoci ktereho by se delalo related query:

$tbl = $database->table('application')->where('authorId = ?', $authorId);
$tbl->referenceHint('application_tag', 'application.authorId = ?', $authorId); // pouzij join

Selection::getReferencingTable() by pak pouzila tento hint, pokud by byl dostupny. U me se to dela 10ti nasobne zrychleni (10s → 1s)

Editoval juzna.cz (6. 3. 2012 0:17)

hrach
Člen | 1834
+
0
-

@juzna.cz

  • zaloz nove vlakno
  • napis verzi nette, testuj na nightly
  • poradne osvetli, co se ti nelibi
  • postni neoptimalni dotazy
  • postni, jak by ty optimalni meli vypadat
  • postni klicove casti struktury db pro pochopeni
Dawe3081
Člen | 2
+
0
-

Ahoj, s Nette začínám. Můžu se zeptat jak by se z uvedené databáze získaly všechny odpovídající záznamy z tabulky application, pokud zadám tag.name? SQL kód by vypadal asi takto:

/--application.title,application.web, application.slogan
from application, application_tag, tag
where application.id=application_tag.application_id and
tag.id = application_tag.tag_id and
tag.name = $name\--

Děkuji za odpovědi.

Editoval Dawe3081 (26. 4. 2013 16:50)

hrach
Člen | 1834
+
0
-
$c->table('application')->where(':application_tag.tag.name', $mytag);