Základní principy dotazování do DB – model vs presenter

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

Zdravím,
asi to bude hodně začátečnický dotaz, ale cítím že mi chybí poslední dílek skládačky.

Jaké jsou pravidla pro dotazování do DB? (celkově s prací DB)

Aktuálně mám veškeré dotazování v modelu (čtení/zápis), ale nevím, jestli můžu mít dotazování i v presenteru.

Mám v tom aktuálně zmatek.

Například pokud chci vykreslit data, stále píši {foreach $posts as $post} (i když vím že bude pouze 1), protože nevím jak to jinak napsat. Mám např. toto:

Model:

public function getItemData($id)
{
    return $this->database->table(self::ITEM_TABLE)
        ->where(self::ITEM_ID, $id)
        ->limit(1);
}

Presenter:

public function renderItem($id)
  {
      $this->template->items = $this->itemManager->getItemData($id);
  }

Latte:

{foreach $items as $item}
 	{$item->name}
	//zde vypíšu potřebná data
{/foreach}

Můžu toto napsat v modelu? (tuším že zrovna tohle mi nefungovalo)

$this->database->table('item')->get($itemID);

Mám v tom docela bordel kde co psát a jak… Dokumentaci jsem si prošel několikrát, část aplikace mám funkční, ale pořád to není ono a často zápasim se zápisem :-( Prostě nevím kde a kdy je vhodné používat věci z Nette/Database, ActiveRow, Selection, Table…

Taky mám bordel v tom, kdy a kde se používá fetch()…

Editoval Croc (2. 9. 2015 19:55)

Namespace
Člen | 81
+
0
-

Ahoj,
práce s databází by měla probíhat vždy v modelu. Do šablon si posílej už jen data.

Tohle

<?php
$this->database->table('item')->get($itemID);
?>

by jsi měl používat vždy v modelu.

Jinak se dá obecně říci, že v modelu je všechna aplikační logika, práce s daty atp. Presentery zajišťují komunikaci mezi modelem a pohledem. A pohled už jen vykresluje. Takže metody fetch(), fetchAll() atd by měly být volány v modelu :).

Azathoth
Člen | 495
+
+1
-

pokud ti v modelu nefungovalo volání

<?php
$this->database->table('item')->get($itemID);
?>

ujisti se, že máš naplněnou proměnnou database a že požadouvanou závislost database dostává tvá modelová třída v konstruktoru (obecně, vždycky, když ti něco nefunguje, si pozorně přečti chybovou hlášku, ta ti většinou řekne, kde je zakopaný pes).
Samozřejmě v různých návodech a ukázkách někdy vidíš, že se sahá do databáze v presenterech, ale to je použitelné pouze u velmi malé aplikace, u větších aplikací je nutné to mít v modelu, protože ti roste množství kódu a musíš to tak mít přehlednější, aby se v tom dalo orientovat a aby se ti neduplikovala logika.

Některé náhledy na to, jak poznat, co kam patří se řídí tímto: model se stará o data, tedy pokud bys sql databázi vyměnil např. za nějakou nosql databázi nebo soubory/rest api klienta/cokoli jiného, presentery by se vůbec neměly změnit. tedy, musel bys akorát přepsat modelové třídy, aby načítaly data odjinud, ale presenterům je vracely stále stejně.
A naopak, pokud bys například dělal rest api pro svou aplikaci (nebo jiný způsob „zobrazení“ dat), nemělo by to vůbec ovlivnit tvůj model, tedy ten by měl poskytovat stále stejná data, a pouze bys vyměnil presentery, které jsou zodpovědné za servírování dat uživateli. Jsou výjimky, ale tohle je obecná a podle mne dobrá poučka.

Croc
Člen | 270
+
0
-

Díky moc za ujasnění. Už mi je to jasnější :-) Trochu jsem si s tím pohrál a konkrétně mi už ->get($itemID) funguje.

blaztar
Člen | 93
+
-5
-

Dotazy můžeš mít klidně v presenteru. Svět se nezboží, ale nějaký model je fajn.

Jinak nevidím u tebe v příkladech metody fetch, fetchAll apod..

Chceš jeden konkrétní záznam..

$this->database->table(self::ITEM_TABLE)->('neco', $neco)->fetch();

Pokud hledáš pomocí primárního klíče pak stačí psát:

$this->database->table(self::ITEM_TABLE)->get($id);

Je to kratší zápis..

$this->database->table(self::ITEM_TABLE)->where('primarni_klic', $primarniKlic)->fetch();

Chceš všechny záznamy..

$this->database->table(self::ITEM_TABLE)->fetchAll();

Chceš konkrétní hodnotu z jednoho řádku..

$this->database->table(self::ITEM_TABLE)->where('neco', $neco)->fetchField('sloupec');

Pak jsou i další metody fetchPairs, fetchAssoc.

Editoval blaztar (2. 9. 2015 22:24)

one-two
Člen | 80
+
+5
-

blaztar napsal(a):

Dotazy můžeš mít klidně v presenteru. Svět se nezboží, ale nějaký model je fajn.

Dal sem mínus, vysvětlim proč.

Tohle sem udělal na jednom menšim projektu, kde sem si přesně říkal, že se svět nezboří a když sem pak měl projekt rozšiřovat, tak sem se sám proklínal.
Podobně se to dá brát s formulářema v presenteru místo vlastní FormFactory. Je to jen o trošičku psaní navíc ze začátku, ale do budoucna se to prostě vyplatí. Radši jednou a pořádně hned i u malého projektu.

Šaman
Člen | 2666
+
+2
-

ad dotazování z presenteru: Já tomu říkám VC architektura (view-controller, neboli záchodová). Ale úplně bych ji nezatracoval – pokud přijde nováček k Nette, tak má dost starostí vůbec rozchodit nějaký „Hello world!“ a jednoduché odkazování mezi stránkami. Pak ať klidně prasí dotaz do presenteru. Jako překlenovací období to stačí, framework mu i tak přináší brutálně hodně výhod oproti čistému PHP. Dokud si nezažije základy, tak je model zbytečná komplikace z droj dalších záseků.
Samozřejmě, že jakmile si osvojí základy a napíše první malé projekty, tak by měl přejít na model, ale to už zjistí sám.

@Croc: Vzhledem ke kontextu úvodní otázky už ale dotazováni z presenteru relevantní není. Když už máš model, tak presenter o databázi nesmí vůbec vědět. Kvůli konzistenci kódu, testování, nebo předcházení WTF momentů až to budeš za půl roku upravovat.

Croc
Člen | 270
+
0
-

Trochu jsem se v Nette rozkoukal, něco málo už mám naprogramováno, ale pořád mi neseděly dotazy na DB v presenteru. Tak jsem je dal do modelu (opakovaly se stejné, kterým by slušela jedna metoda), ale s některýma jsem měl následně problém (trochu jiný zápis, ale už vyřešeno). Také mě dost mátlo, že v dokumentaci jsou dotazy v presenteru (už teď chápu, že je to pro jednoduchost vysvětlení). Pak jsem psal sem, protože jsem v tom měl už opravdu guláš.

Aktuálně mám veškerou komunikaci s DB v modelu a je to opravdu o dost přehlednější a čistší.

Ještě jednou všem moc děkuju za rady, dost mi to pomohlo si ujasnit nejasnosti. Díky moc :-)

Šaman
Člen | 2666
+
0
-

Croc napsal(a):

Také mě dost mátlo, že v dokumentaci jsou dotazy v presenteru (už teď chápu, že je to pro jednoduchost vysvětlení)…

Problém je, že na model neexistuje žádné Best practise. Resp. každý má svoje. Takže třeba v ukázkách práce s databází je jen dotaz v presenteru, předaný výsledek do šablony a tam se to nějak vypíše. A jakou si pak zvolíš strukturu aplikace a modelu, to už je na tobě a hodně záleží i na typu aplikace, kterou píšeš.

newPOPE
Člen | 648
+
0
-

@one-two: to ze si dal – lebo si to niekedy na danom projekte zpatlal je tvoja skusenost (nic v zlom). Akonahle sa projekt zacal rozrastat tak by nebolo zle pri novej feature „nieco upravit“ (myslim tym prepisat cast veci z presenteru do modelu). Schvalne nepisem refaktor lebo by som zavadzal.

@croc: ano dotazy kludne na zaciatku mozes pisat do presenterov (nakolko nette ti nejaky pristup ako ine frameworky nenuti). Dolezite ale neskor budu upravy projektu a tam nezabudaj na to, ze pri zmene funkcionality mozes vzdy kusok upravit/zlepsit tak aby zmeny mali prinos do buducna. (Znizujes tym technicky dlh).

Este mozno jedno doporucenie. K Nette sa staviam tak ze je to len jedna z vstupno/vystupnych vrstiev aplikacie medzi modelom (business logikou) a userom. Cize UI s ktorym useri interaguju. Dalsi priklad takej vrsty moze byt napriklad API… No a potom ti docvakne preco, ako pise @Šaman, nie je jednoducha tema.