Jak se správně k dostat k core funkcím aktuálního Presenteru?
- snazimse
- Člen | 43
Zdravím,
chci se zeptat, pořád dost věcí v tom Nette mi nejde do hlavy a ani jsem
to moc, ze základních příkladů.
Tak se radši zeptám zkušenějším, než to dělat
nějak blbě.
Jaký je systém v Nette, Presenter je základ, tam všechno je, to je
jasný.
Chápu, že do Presenteru není dobré napráskat 5 tisíc řádků a je dobré
si vytvářet komponenty přes
Továrničky, ale nějak rychle nemůžu pochopit, jak správně se dostat
k core funkcím dostupných běžně v Presenteru, jako např
flashmessage.
Mám nějaký formulář v samostatném souboru a složce jako komponentu přes generovanou továrničku.
public function __construct(\Kdyby\Doctrine\EntityManager $EntityManager, Nette\Http\Request $httpRequest) {
$this->httpRequest = $httpRequest;
$this->EntityManager = $EntityManager;
parent::__construct();
$this->buildForm($this->httpRequest->getQuery('id'));
}
/** @return AdEditForm */
public function buildForm($id) {
if ($id) {
$getAdsModel = new InzeratModel($id,$this->EntityManager);
}
$get_ad = $getAdsModel->doctrine_ORM_getRepositoryFindCurrent();
$form = $this->form;
$name = get_class($this);
//ajax only
//$form->getElementPrototype()->class( 'ajax' );
$form->action .= '?id='.$id;
$form->addText('title', 'Titulek ')
$form->setDefaults([
'title' => $get_ad->title,
'content' => $get_ad->content,
'id' => $id
]);
$form->onValidate[] = [$this, 'validateAdEditForm'];
return $form;
}
public function validateAdEditForm($form) {
$values = $form->getValues();
//error zde
if(empty($values["content"]))
// potrebuju vazbu na $this->presenter
$this->presenter->flashMessage('Content is empty !');
return;
}
Chtěl bych tam provést vlastní validaci, a nevím jak se dostat, např k redirectu, nebo flashMessage v mnoha implementacích jsem viděl $this->presenter, ale kdo ho mám vzít, když v něm nejsem? Ani nevím, jestli tu validaci mám provádět zde, ale nechci to přece prát všechno do Presenteru, ale jak se dostat k těmto funkcím, nebo ideálně k $this->presenter u některých implementací jsem to viděl přes model, ale opět stejná otázka jak to dostat do modelu, aktuální presenter, chápu, že klasicky si přidám nějakou knihovnu, nebo tak, ale tohle jsem nějak nepochopil, rád bych dostal echo, jak to správně řešit…
V dokumentaci vidím např: https://doc.nette.org/…n/components#…
Že se tam předává jen Model předpokládám, že ten Model by měl mít
vazbu na Presenter.
Čili je to takto? Presenter>Model>Komponenta ?
Díky moc !
Editoval snazimse (29. 8. 2017 15:30)
- Šaman
- Člen | 2666
V presenteru: $this JE presenter
V komponentách: $this->presenter je definované od
okamžiku, kdy je komponenta připojená k presenteru. Laicky řečeno vždy,
kromě konstruktoru té komponenty.
Jinde bys neměl mít potřebu funkce presenteru volat (teda, při běžném použití Nette). Pokud bys měl nějakou atypickou architekturu, tak bych nejspíš použil události, které si presenter musí odchytit: https://pehapkari.cz/…ce-udalosti/
Co se modelu týče, tak model by neměl mít žádnou vazbu na presenter. Model by měl být zcela nezávislý. Presenter, nebo konponenta si model vyžádá, předají mu vše potřebné a nechají si vrátit výsledky. Ale model, v ideálním případě, vůbec nic o presenterech, ani MVC, neví.
Editoval Šaman (29. 8. 2017 15:58)
- snazimse
- Člen | 43
Šaman napsal(a):
V presenteru: $this JE presenter
V komponentách: $this->presenter je definované od okamžiku, kdy je komponenta připojená k presenteru.
A jak se to tam připojuje?
Nějak takhle?
https://doc.nette.org/…n/presenters#…
Moc to nechápu jak to mám zapsat :(
Šaman napsal(a):
Co se modelu týče, tak model by neměl mít žádnou vazbu na presenter. Model by měl být zcela nezávislý. > Presenter, nebo konponenta si model vyžádá, předají mu vše potřebné a nechají si vrátit výsledky. Ale model, >v ideálním případě, vůbec nic o presenterech, ani MVC, neví.*
Jo ok, jak tedy nejlépe řešit to množství věcí v presenteru, abych
neměl v Presenteru 5 tisíc řádků např.
Je dobré si vytvořit nějaké pomocné třídy, když to nenacpu do
komponent?
Díky moc za reakci !
Editoval snazimse (29. 8. 2017 15:58)
- Šaman
- Člen | 2666
Připojování komponent probíhá automaticky, pokud je tvoříš továrničkou v presenteru. Samotná továrna na komponentu může být velká a v samostatném souboru, v presenteru pak jen vytvoříš onu komponentu v tovární metodě jediným řádkem.
Co se obsluhy třeba flashmessage týče, tak používám tohle řešení: https://gist.github.com/…00f58376e76c
Definici formuláře považuji za třídu modelu (i když o tomhle se vedou
spory). Formulář o presenteru nic neví. Zato presenter samozřejmě ví,
jaký model si načítá a jak ho donastavit. Takže v presenteru se použije
továrna na předpřipravený formulář, ale ještě si tam presenter dodá
nějaká nová tlačítka pro různá přesměrování a flash zprávy.
Všimni si, že už v té základni továrně na formulář, která
o presenteru neví, používám $this->presenter
(úplně
poslední řádek v posledním souboru). Počítám s tím, že nebudu nikde
vytvářet formulář ručně pomocí operátoru new, ale jako komponentu
pomocí createComponent
v presenteru, která zajistí
i připojení.
(Pro úplnost – to volání $this->presenter
z formuláře není úplně čisté a celá ukázka je o tom, jak se tomu
vyhnout. Tenhle jeden řádek by neměl nikdy nastat a je to jen pojistka pro
zapomnětlivé programátory, kteří neošetřili tento formulář
z presenteru. A taky to vyhazuje chybu user_notice, aby si toho všimli.)
Editoval Šaman (29. 8. 2017 16:17)
- snazimse
- Člen | 43
Šaman napsal(a):
Připojování komponent probíhá automaticky, pokud je tvoříš továrničkou v presenteru. Samotná továrna na komponentu může být velká a v samostatném souboru, v presenteru pak jen vytvoříš onu komponentu v tovární metodě jediným řádkem.
Co se obsluhy třeba flashmessage týče, tak používám tohle řešení: https://gist.github.com/…00f58376e76c
Definici formuláře považuji za třídu modelu (i když o tomhle se vedou spory). Formulář o presenteru nic neví. Zato presenter samozřejmě ví, jaký model si načítá a jak ho donastavit. Takže v presenteru se použije továrna na předpřipravený formulář, ale ještě si tam presenter dodá nějaká nová tlačítka pro různá přesměrování a flash zprávy.Všimni si, že už v té základni továrně na formulář, která o presenteru neví, používám
$this->presenter
(úplně poslední řádek v posledním souboru). Počítám s tím, že nebudu nikde vytvářet formulář ručně pomocí operátoru new, ale jako komponentu pomocícreateComponent
v presenteru, která zajistí i připojení.(Pro úplnost – to volání
$this->presenter
z formuláře není úplně čisté a celá ukázka je o tom, jak se tomu vyhnout. Tenhle jeden řádek by neměl nikdy nastat a je to jen pojistka pro zapomnětlivé programátory, kteří neošetřili tento formulář z presenteru. A taky to vyhazuje chybu user_notice, aby si toho všimli.)
Jojo tak v té továrně metoda afterSave bereš ten odkaz na presenter z toho formuláře jo? Už jsem to pochopil, to hlavně o co mi šlo, že jsem nějak nepochopil, že v metodě která vytváří komponentu lze vlastně pracovat s daty, já to pořád chtěl řešit v té komponentě, takže se to vlastně v komponentě vůbec neřeší…
Já měl představu takovou že v presenteru budu jen a pouze vytvářet komplet hotovou komponentu, ne že tam budu řešit ty zprávy… Takže Validaci, kde bych chtěl použít flashmsg, tak bych měl taky řešit až v Presenteru jo, stejně jako onSuccess ?
Proč vlastně nepoužíváš to autogenerování továrničky jen z rozhraní? Nefunguje to podobně?
Jinak pěkné a přehledné řešení :)
Díky !
- Šaman
- Člen | 2666
Ona je to trochu filosofická otázka. U flashových zpráv ještě chápu,
že si je chce spravovat komponenta sama.
U formulářů ale dochází k redirectu a tam už formulář sám nemůže
rozhodnout, kam se bude redirectit. Protože o struktuře stránek obyčejný
formulář nemá nic vědět. Proto to ošetřuji v presenteru, který si
navíc přidává druhé odesílací tlačítko a podle tlačítka přesměruje
buď na detail právě vloženého záznamu, nebo na seznam. To je logika,
která je mimo kompetence formuláře. (A hodí se to třeba pokud stejný
formulář používám na frontendu a v backendu. Pokaždé se přesměruje
jinam, spravuje to presenter.)
Co se generované továrny z rozhraní týče – to je jen zkratka pro elementární vytvoření komponenty ze třídy. Ale já v té továrně skládám celý formulář, proto to v tomhle případě nepoužívám. Jinde ano.
Mimochodem v tomhle příkladu je i ukázka práce s jednoduchým modelem (v tomto případě ORM repozitář). Komponenta, nebo nějaká vyšší třída modelu si ho vyžádá přes konstruktor a presenter se pak vůbec nedozví, jak to ten formulář vlastně ukládá. Je mu to jedno. Pro presenter je formulář černá skříňka, do které musí jen nastavit, kam se bude po odeslání redirectovat.
A pro formulář je černá skříňka onen repozitář. Jen ví, že nad
ním může zavolat metodu persist($entity)
a
get($id)
.
A repozitář neví nic o existenci formuláře, natož o presenteru. Repozitář je jen nízkoúrovňová třída modelu.
- snazimse
- Člen | 43
Šaman napsal(a):
Ona je to trochu filosofická otázka. U flashových zpráv ještě chápu, že si je chce spravovat komponenta sama.
U formulářů ale dochází k redirectu a tam už formulář sám nemůže rozhodnout, kam se bude redirectit. Protože o struktuře stránek obyčejný formulář nemá nic vědět. Proto to ošetřuji v presenteru, který si navíc přidává druhé odesílací tlačítko a podle tlačítka přesměruje buď na detail právě vloženého záznamu, nebo na seznam. To je logika, která je mimo kompetence formuláře. (A hodí se to třeba pokud stejný formulář používám na frontendu a v backendu. Pokaždé se přesměruje jinam, spravuje to presenter.)Co se generované továrny z rozhraní týče – to je jen zkratka pro elementární vytvoření komponenty ze třídy. Ale já v té továrně skládám celý formulář, proto to v tomhle případě nepoužívám. Jinde ano.
Mimochodem v tomhle příkladu je i ukázka práce s jednoduchým modelem (v tomto případě ORM repozitář). Komponenta, nebo nějaká vyšší třída modelu si ho vyžádá přes konstruktor a presenter se pak vůbec nedozví, jak to ten formulář vlastně ukládá. Je mu to jedno. Pro presenter je formulář černá skříňka, do které musí jen nastavit, kam se bude po odeslání redirectovat.
A pro formulář je černá skříňka onen repozitář. Jen ví, že nad ním může zavolat metodu
persist($entity)
aget($id)
.A repozitář neví nic o existenci formuláře, natož o presenteru. Repozitář je jen nízkoúrovňová třída modelu.
Díky, díky moc… Já jsem doplatil na to, že jsem si vytáhl nějaký příklad s tím autogenerování továrničky a jsem se do toho zamotal, jsem myslel, že se nemusím o nic starat, :D A to jsem se teda spletl, díky za tvůj případ v podstatě to máš vlastní továrničku na Formuláře, což jsem myslel, že se nějak auto-generuje v té generované(jsem vytrhl z kontextu), ale bylo mi to divné to prázdné rozhraní, na formuláře se to nedá vůbec použít, přesto jsem takový příklad viděl, tak jsem se toho blbě chytl, nebo to asi špatně pochopil…
Vycházel jsem z tohoto postupu: https://forum.nette.org/…i-komponenta#…
Nevím na co by jako měl být dobrý takový formulář v kterém se nedá nic dělat…
Editoval snazimse (29. 8. 2017 22:55)
- Šaman
- Člen | 2666
No jo, v tomhle je trochu chyták. Ten odkazovany příspěvek totiž
začíná:
„Vytvoříš si třídu, která má zděděný UI\Form kde si ho sestavíš
($this->addText(…))…“ a ta továrnička v ukázce pak vrací instanci
třídy MyForm
.
To je jiný přístup k tvorbě formulářů!
Já žádný MyForm extends \Nette\Application\UI\Form
nemám.
Mám továrničku, která nemusí od ničeho dědit a v ní si vytvořím nový
formulář a ten nakonfiguruji a vrátím. (Jen to mám rozhozené do dvou
tříd – FormFactory
vrátí základní kostru všech mých
formulářů a konkrétní FooFormFactory
k tomu přidá inputy a
validaci. Můžeš to mít ale v jediné třídě.)
Takže já píšu rovnou tovární třídu.
V té tvoji ukázce je nejprve vytvořená třída MyForm
,
která představuje připravený formulář a následně je tou generickou
továrničkou pouze vytvořená instance a ta se předá presenteru.
A přesně na to ta továrničká pomocí rozhraní je. Já to používám
třeba na komponenty. Mám hotovou komponentu (třída dědící z
Nette\Application\UI\Control
) a pomocí rozhraní ji nechám
vytvořit a předat do presenteru. Tam ta továrnička nemusí řešit nic
složitého…