Jak se správně k dostat k core funkcím aktuálního Presenteru?

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

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
+
0
-

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
+
0
-

Š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
+
0
-

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
+
0
-

Š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 !

CZechBoY
Člen | 3608
+
0
-

@snazimse Automaticky generovaná továrna nejde moc uzpůsobit. Automaticky generovaná továrna zavolá jen create a tím v 99% končí (záleží ještě na konfiguraci služby v config.neon).

snazimse
Člen | 43
+
0
-

CZechBoY napsal(a):

@snazimse Automaticky generovaná továrna nejde moc uzpůsobit. Automaticky generovaná továrna zavolá jen create a tím v 99% končí (záleží ještě na konfiguraci služby v config.neon).

Aha, já myslel, že právě dělá něco více…

Šaman
Člen | 2666
+
0
-

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
+
0
-

Š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) a get($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
+
0
-

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…

snazimse
Člen | 43
+
0
-

Jojo, už chápu :) Ještě jednou díky, fakt mi to pomohlo…