Formuláře samostatně v souborech
- Rndoom04
- Člen | 75
Zdravíčko,
netušíte jak správně udělat jednotlivé komponenty formulářů zvlášť
do souborů?
Totiž cílem má být to, že basePresenter má obsahovat třeba 20 různých formulářů – budou předpřipravené a klient si bude moci navolit, které chce kde zobrazovat. V basePresenteru to má být z důvodu, že formuláře se mohou na webu vyskytovat kdekoliv (na libovolné stránce). Zapisovat všechny možné formuláře do jednoho BasePresenter.php opravdu nechci, proto bych je rád osamostatnil např. do souborů a pak je něčím includnul. Ale nemám tušení, jak na to.
Děkuji za popostrčení. :)
- Marek Bartoš
- Nette Blogger | 1280
I komponenty mohou mít komponenty. Takže si vytvoříš třídu komponenty a ta bude obsahovat komponentu s celým formulářem. Namísto formuláře tak vykresluješ jen tu obalující komponentu.
https://doc.nette.org/…n/components#…
Editoval Marek Bartoš (24. 7. 2022 16:05)
- Marek Znojil
- Člen | 90
Ahoj, na tohle by se mohl hodit accessor:
https://doc.nette.org/…tion/factory#…
- Marek Bartoš
- Nette Blogger | 1280
Marek Znojil napsal(a):
Ahoj, na tohle by se mohl hodit accessor:
https://doc.nette.org/…tion/factory#…
Tím se řeší injectování závislostí a jejich lazy-loading, nikoli oddělení komponent do samostatných tříd/souborů. Je to krok navíc.
A když už, tak na komponenty se má používat factory, ne accesor (create() namísto get()) – jinak bys jednu komponentu nemohl na stránce vykreslit vícekrát.
- Rndoom04
- Člen | 75
Děkuji všem za odpovědi. Přesně jak se tu píše.
Aktuálně mám 20× v basePresenter.php createComponentNejakyNazevForm a celá tato komponenta zabírá třeba i 100 řádků. Protože je mnoho inputů a nějaké to následné zpracování. Takže je to aktuálně velmi nepřehledné. Tento způsob mi vyhovoval, dokud jsem měl jen pár formulářů, ale usnadnilo by mi to, když bych celou tu komponentu vzal, strčil do souboru, ty už jen naincludoval a měl něco jako:
// Formuláře typu aaa
require_once(APP_DIR."/Model/Formulare/aaa/form1.php");
require_once(APP_DIR."/Model/Formulare/aaa/form2.php");
require_once(APP_DIR."/Model/Formulare/aaa/form3.php");
// Formuláře typu bbb
require_once(APP_DIR."/Model/Formulare/bbb/form1.php");
require_once(APP_DIR."/Model/Formulare/bbb/form2.php");
require_once(APP_DIR."/Model/Formulare/bbb/form3.php");
Editoval Rndoom04 (25. 7. 2022 17:54)
- Marek Bartoš
- Nette Blogger | 1280
require_once(APP_DIR.„/Model/Formulare/aaa/form1.php“);
Tohle nikdy dělat nebudeš, od načítání souborů je autoloading. V app/Bootstrap.php ve výchozím nastavení máš robotloader, který hledá třídy v app složce. Eventuelně je standard používat PSR-4 https://getcomposer.org/…04-schema.md#…
Teď děláš v presenteru něco takového
namespace Example\Presenter;
class ExamplePresenter extends \Nette\Application\UI\Presenter
{
public function createComponentReportForm(): Form
{
$form = new \Nette\Application\UI\Form();
// ...
return $form;
}
}
Kód formuláře vůbec nemusíš mít v presenteru, můžeš si vytvořit komponentu
namespace Example\Control;
class ReportControl extends \Nette\Application\UI\Control
{
public function render(): void
{
$this->template->setFile(/* TODO - vytvoříš si latte soubor, vypíšeš v něm formulář a sem předáš cestu k souboru */);
$this->template->render();
}
public function createComponentForm(): Form
{
$form = new \Nette\Application\UI\Form();
// ...
return $form;
}
}
Pro komponentu si vytvoříš factory (ta slouží pro předávání
závislostí, abys v presenteru nemusel psát
new ExampleControl($this->dep1, $this->dep2, ...)
a
předávat závislosti přes něj)
namespace Example\Control;
interface ReportControlFactory {
public function create(): \Example\Control\ReportControl;
}
Factory zaregistruješ v neonu a Nette ti pro ni vygeneruje třídu vytvářející ReportControl:
services:
- Example\Control\ReportControlFactory
V presenteru nakonec vypíšeš jen komponentu z factory
namespace Example\Presenter;
class ExamplePresenter extends \Nette\Application\UI\Presenter
{
/** @inject **/
public \Example\Control\ReportControlFactory $reportControlFactory;
public function createComponentReportForm(): \Example\Control\ReportControl
{
return $this->reportControlFactory->create();
}
}
Tím se ti kód v presenteru zredukuje na volání create() metody a na získání služby z DI.
Editoval Marek Bartoš (25. 7. 2022 16:13)
- Rndoom04
- Člen | 75
Děkuji za odpověd. Mám pocit, že už jsem to někdy v minulosti takto řešil. Cílem jsem měl úplně zredukovat i tu public function createComponentReportForm(), ale co nadělám.
Nicméně zkoušel jsem vytvořit traitu i továrničku via (https://doc.nette.org/…in-presenter), ale hlásí mi to „Cannot declare class TestFormFactory, because the name is already in use“. Totiž ať si tam vymyslím jakýkoliv název, který jsem opravdu nikdy nepoužít nemohl, stále mi to hlásí. Netušíte někdo, v čem dělám chybu?
V common.neon to mám, use jsem také použil. Nerozumím tomu. :(
- Marek Bartoš
- Nette Blogger | 1280
Cannot declare class TestFormFactory, because the name is already in use
Nepoužíváš někde require nebo include? Ty soubory se vážně načítají samy, nemusíš je načítat sám.
- Petr Parolek
- Člen | 455
Rndoom04 napsal(a):
Děkuji za odpověd. Mám pocit, že už jsem to někdy v minulosti takto řešil. Cílem jsem měl úplně zredukovat i tu public function createComponentReportForm(), ale co nadělám.
Nicméně zkoušel jsem vytvořit traitu i továrničku via (https://doc.nette.org/…in-presenter), ale hlásí mi to „Cannot declare class TestFormFactory, because the name is already in use“. Totiž ať si tam vymyslím jakýkoliv název, který jsem opravdu nikdy nepoužít nemohl, stále mi to hlásí. Netušíte někdo, v čem dělám chybu?
V common.neon to mám, use jsem také použil. Nerozumím tomu. :(
Řešil jsem to a jde to viz https://github.com/…nets-sandbox
- Marek Bartoš
- Nette Blogger | 1280
Nejspíš nemáš duplicitu, ale nějaký autoloader se snaží stejnou třídu načítat 2×.
Nastavoval jsi si kromě robot loaderu v Bootstrap i Composer nebo nějaký
jiný autoloader? Jak je máš nastavené?
Tahle chyba se dá spolehlivě izolovat tak, že vyřadíš všechny
autoloadery, v Composer json si složku s appkou namapuješ přes classmap a
zavoláš composer dump
.
Sice pak bez manuální obnovy autoloaderu nefunguje přidávání nových tříd, ale aspoň budeš mít jistotu že je to ono. Pak můžeš řešit třeba jak přes PSR-4 načítat všechny soubory
Seznam autoloaderů zjistíš tak, že před vrácením Configurator
v Bootstrap vypíšeš bdump(spl_autoload_functions());
To co posílá Petr spočívá v přetížení metody createComponent(), abys mohl to kde se hledají komponent řešit sám a ne přes createComponentExample(). Bez znalosti tvého usecase těžko říct, zda je to pro tebe použitelné a může to být dost omezující. Nemá cenu řešit, dokud nemáš hotové alespoň oddělení komponent a factories pro ně
Editoval Marek Bartoš (25. 7. 2022 18:39)
- Pepino
- Člen | 257
Co se týče minimalizace kódu tak bych jen chtěl přidat ještě 2 poznatky.
- Každou továrničku není potřeba registrovat zvlášť. Existuje přece https://doc.nette.org/…onfiguration#…
- Vytváření komponenty v presenteru taky nevyžaduje psát
createComponentXXX, stačí např. v action metodě
napsat
$this['mujFormular'] = $this->mujFormularFactory->create();
PS: Nepíšu nic o přehlednosti, ale jen o minimalizaci kódu.
Editoval Pepino (26. 7. 2022 8:21)