Form, Database Explorer, prosím o radu

MW
Člen | 626
+
0
-

Zdravím, prosím o názor k tomuto kódu.

Je toto správný postup?

V presenteru je načtený formulář z továrny. Mám jeden Model, který vrací explorer->table(), tj settings->getSettingsTable().

Ptám se především proto, že se mi nejak nezdá, jestli je dobře ten setDefaults()->fetch()->, jinak jsem to tam nedostal a trochu nechápu, proč, když to vrací následující prvek… podle doc..
A také, jestli je opravdu practice, to takto obsluhovat v presenteru, ted myslím ten update().

Takto jsem to pochopil z dokumentace.

Předem moc děkuji za názor a rady, vracím se k Nette po 6ti letech, tak se učím hodně věcí znovu :).

protected function createComponentNastaveniForm(): Form {

	$form = $this->nastaveniFactory->create();
	$form->setDefaults($this->settings->getSettingsTable()->fetch());

	$form->onSuccess[] = function ($form) {

	$this->settings->getSettingsTable()->update($form->values);

	$this->flashMessage("Nastavení uloženo.");
	$this->redirect('Nastaveni:');

	};
	return $form;
    }

Editoval MW (27. 6. 21:19)

Šaman
Člen | 2653
+
+1
-

MW napsal(a):

Ptám se především proto, že se mi nejak nezdá, jestli je dobře ten setDefaults()->fetch()->, jinak jsem to tam nedostal a trochu nechápu, proč, když to vrací následující prvek… podle doc..

Vždyť nevoláš $form->setDefaults()->fetch(), to by opravdu nedávalo smysl.
Ty voláš $form->setDefaults( $db->query()->fetch() ). Fetch je v tomto případě potřeba, protože do setDefaults máš předat pole dat, nikoliv aktivní databázový dotaz. (Resp. ty nad db nevoláš query, ale to je jedno, obecně přistupuješ k datům a pak si fetchneš výsledek.)

Navázat obsluhu update v presenteru je ok. Záleží jakou máš strukturu aplikace. Já mám formuláře v modelu, ale používám orm, takže formulář je vedle entity, kterou upravuje. Základní obsluha je pak také navázaná v tom modelu, ale minimálně redirect si má řešit až ten presenter.

Editoval Šaman (27. 6. 21:36)

MW
Člen | 626
+
0
-

Šaman napsal(a):

MW napsal(a):

Ptám se především proto, že se mi nejak nezdá, jestli je dobře ten setDefaults()->fetch()->, jinak jsem to tam nedostal a trochu nechápu, proč, když to vrací následující prvek… podle doc..

Vždyť nevoláš $form->setDefaults()->fetch(), to by opravdu nedávalo smysl.
Ty voláš $form->setDefaults( $db->query()->fetch() ). Fetch je v tomto případě potřeba, protože do setDefaults máš předat pole dat, nikoliv aktivní databázový dotaz. (Resp. ty nad db nevoláš query, ale to je jedno, obecně přistupuješ k datům a pak si fetchneš výsledek.)

Navázat obsluhu update v presenteru je ok. Záleží jakou máš strukturu aplikace. Já mám formuláře v modelu, ale používám orm, takže formulář je vedle entity, kterou upravuje. Základní obsluha je pak také navázaná v tom modelu, ale minimálně redirect si má řešit až ten presenter.

Moc díky! Jen ten fetch() není asi úplně šťastně popsán v DOC… nebo jsem to přehlédl.

Editoval MW (27. 6. 21:45)

Šaman
Člen | 2653
+
0
-

Aha, sorry, teprve teď jsem pochopil jak jsi to myslel. Nj, je to divný. Nějak jsem myslel, že voláš fetchAll, nebo fetchPairs – to druhé je právě pro plnění třeba selectboxů ve formuláři.

Nevím co přesně ten formulář zpracovává, z toho dotazu to chápu tak, že ho nakrmíš jedním (prvním?) řádkem z tabulky settingsTable. Doporučuji si dumpnout data dřív, než je předáš do toho formuláře. Protože tady se řeší dvě různé věci – formulář a načtení dat z databáze.

m.brecher
Generous Backer | 814
+
0
-

@Šaman

Já mám formuláře v modelu, .....

To mě přijde jako zajímavý koncept.

V jaké formě máš tyto formuláře vytvořené ?? Jako traity, které obsahují metodu createComponent<Form>(), nebo jako plnohodnotnou třídu poděděnou z UI\Control, která “obaluje” vlastní Form ??

Poznámka: @KamilValenta používá opačný koncept než ty, kdy umisťuje modelové třídy do složky presenteru a má tak pohromadě vše co presenter používá – formuláře, modelové třídy, šablony a samotný presenter.

Šaman
Člen | 2653
+
0
-

@mbrecher : Jako FooFormFactory. Typicky mám třídu Entity, její FormFactory a většinou GridFactory. Někdy i Datasource, pokud je to entita rozlezlá přes několik tabulek, někdy i třída pro práci s kolekcí entit. Všechno to mám pod modelem, protože když sáhnu na entitu, budu asi upravovat i vsechny ostatní. A stále to souvisí s datovou vrstvou, nikoliv s prezenční vrstvou.

Že to má Kamil jinak vím, proto píšu že nastavování v presenteru může být zcela legit.

m.brecher
Generous Backer | 814
+
0
-

@MW

$this->settings->getSettingsTable()->fetch()

Metoda fetch() knihovny Explorer se dá použít pro čtení řádků z objektu Selection v cyklu např.:

$articles = $database->table('article');
while($article = $articles->fetch()){
    echo $article->title;
}

nebo mimo cyklus dává smysl pokud vybíráme podle sloupce, který má unikátní index a je tak zaručeno, že výběr z tabulky Selection obsahuje pouze jeden řádek:

  $article = $database->table('article')->where('title', $title)->fetch();  // sloupec title má UNIQUE index

Pro práci s jedním řádkem databázové tabulky ve formuláři nejčastěji používá výběr pomocí metody get($id), nebo where(…) uvedený výše.

Když si rozebereme Tvoje dotazy do databáze:

$this->settings->getSettingsTable()->fetch()

$this->settings->getSettingsTable()->update($form->values)

Tak mě tam chybí výběr řádku z tabulky nějakým parametrem, který by se měl ve formuláři aktualizovat, – třeba $id. Otázkou je, co se skrývá za getSettingsTable(), jestli tam není ten parametr schovaný.

Kamil Valenta
Člen | 783
+
+1
-

m.brecher napsal(a):

Poznámka: @KamilValenta používá opačný koncept než ty, kdy umisťuje modelové třídy do složky presenteru a má tak pohromadě vše co presenter používá – formuláře, modelové třídy, šablony a samotný presenter.

Jen bych upřesnil, že ne do složky presenteru, ale do složky modulu. Modelové třídy jsou vždy v adresáři model. Takže když otevřeš adresář modulu, máš v něm všechny jeho modely, presentery, šablony, neony.
Jen „assets“ jsou ve www, takže zatím je modul na dvou místech (v app a ve www). Asi by i to šlo mít na jednom místě a rozhodil by to až deploy…

Kamil Valenta
Člen | 783
+
+3
-

MW napsal(a):

protected function createComponentNastaveniForm(): Form {

	$form = $this->nastaveniFactory->create();
	$form->setDefaults($this->settings->getSettingsTable()->fetch());

	$form->onSuccess[] = function ($form) {

	$this->settings->getSettingsTable()->update($form->values);

	$this->flashMessage("Nastavení uloženo.");
	$this->redirect('Nastaveni:');

	};
	return $form;
    }

Mně by tady vadilo, že se v presenteru volá update() přímo nad selectionou. Metoda presenteru tedy sahá přímo do db bez vědomí modelu, což není dobře (projeví se, až přibude požadavek na přístupová práva, logování změn apod.)
Za mě by bylo lépe, kdyby přímo modelová třída settings měla svou metodu update().
Tedy:

$form->onSuccess[] = function ($form) {
$this->settings->update($form->values);
$this->flashMessage("Nastavení uloženo.");

V počátku ta metoda klidně jen vše přenese do $this->getSettingsTable()->update(), ale když se později něco změní, upravíš jen update() v settings.

MW
Člen | 626
+
0
-

Tabulka setting obsahuje více sloupců, ale vlastně jen jeden záznam. Jedná se o data nastavení webu. Tabulka nemá klíč, jsou tam věci jako barva, šířka, výška atd.

Tak proto funguje ten fetch(). To mi nedošlo :)

A pravda, ten update asi patří do modelu.

Díky moc!