Odkaz na action chce latte soubor (rozdíl mezi odkaz na action a na presenter)

mimacala
Člen | 113
+
0
-

Ahojte,
jaký je rozdíl v odkazu na Presenter:default.latte a Presenter:Action.

mám tento kód a když kliknu na tlačítko, tak to po mě chce missing template pridatkosik.latte :/

 <div class="col">
                    <div class="card karty  h-100 text-center">
                        <img src="{$basePath}/assets/img/avatar.png" class="card-img-top  w-75 img-profile mx-auto" alt="...">
                        <div class="card-body">
                            <h5 class="card-title">Card title</h5>
                            <p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This card has even longer content than the first to show that equal height action.</p>
                        </div>
                        <div class="card-footer ">
                            <a n:href="Produkty:Pridatkosik 1" class="btn btn-primary"> Přidat do košíku</a> // tady posílám ID do presenteru action
                        </div>
                    </div>
 public function actionPridatKosik(int $idProduktu) // tady zpracovávám
    {
        $kosik = $this->session->getSection('kosik');
        $kosik->set("$idProduktu","$idProduktu");
        if($kosik)
        {
            $this->flashMessage("Zboží bylo přidání do košíku");
        }
    }
Pepino
Člen | 249
+
0
-

Musíš v té metodě actionPridatKosik vrátit nějaký response nebo přesměrovat jinam.

mimacala
Člen | 113
+
0
-

Aha, už to funguje.
Moc děkuji

m.brecher
Generous Backer | 758
+
+1
-

Přidání zboží do košíku je typická funkce kterou řeší nejlépe signál. Pomocí akce presenteru to jde také, má to ale určité nevýhody, které signál nemá. Akce totiž defaultně očekává vykreslení šablony akce. Naproti tomu signál pracuje uvnitř akce/šablony presenteru, nemění ji a automaticky se vykreslí stejná stránka.

Přesměrovat by se ale tak jako tak mělo, protože signál mění obsah databáze – při refreshi stránky se signálem by se samovolně přidalo další zboží.

Signál se pak snadno zapouzdří do komponenty, klidně to ale nech v presenteru

šablona latte:

<a n:href="pridatKosik!, idProduktu: 1" class="btn btn-primary"> Přidat do košíku</a>  //  link volá signál presenteru

presenter:

public function handlePridatKosik(int $idProduktu) // tady zpracovávám
    {
        $kosik = $this->session->getSection('kosik');
        $kosik->set("$idProduktu","$idProduktu");
        if($kosik)
        {
            $this->flashMessage("Zboží bylo přidáno do košíku");
        }
		$this->redirect('this');	// aby se refreshí stránky zboží omylem nepřidalo podruhé
    }

Editoval m.brecher (13. 10. 2022 16:35)

Pepino
Člen | 249
+
-1
-

@mbrecher to úplně tak není pravda, protože ten signál bude fungovat pouze v daném presenteru. Co když chceš přidat zboží do košíku odjinud?

m.brecher
Generous Backer | 758
+
+2
-

@Pepino

signál bude fungovat pouze v daném presenteru

Ano, máš pravdu a tak jsem to i myslel. Pokud přidáváme do košíku jenom v jednom presenteru, tak je OK použít signál presenteru a handler signálu umístit do presenteru.

Pokud by se mělo zboží přidávat do košíku ve více presenterech, potom je optimální pro přidání do košíku si napsat samostatnou komponentu a tu do příslušných presenterů pouze zaregistrovat. To je takový doporučený postup na němž se většina komunity Nette shodne.

V Nette jdou věci obvykle dělat více způsoby. Tvůj způsob znamená ve stručnosti – zpracovávat klik na přidání do košíku v akci presenteru a pak přesměrovat.

Pokud budeme přidávat zboží do košíku ve více presenterech, tak to budeme dělat jak? Buďto budeme volat akci jednoho presenteru k přidání do košíku pověřenému, pak ale musíme přesměrovat zpátky na presenter, odkud se zboží přidávalo – to kód zkomplikuje.

Nebo do každého presenteru dáme akci na zpracování přidání do košíku – to kód zduplikuje.

Nebo presentery, kde se přidává do košíku podědíme ze společného abstraktního presenteru, kde bude společná akce pro přidání do košíku. Také komplikované a nepřehledné řešení.

Komponenta je ideální řešení.

Pepino
Člen | 249
+
-2
-

@mbrecher Komponenty souhlas, ale proč by mělo být komplikace přesměrování z akce zpátky? V nette existuje storeRequest a restoreRequest.

Bulldog
Člen | 110
+
+2
-

Pepino napsal(a):

@mbrecher Komponenty souhlas, ale proč by mělo být komplikace přesměrování z akce zpátky? V nette existuje storeRequest a restoreRequest.

Protože na to redirect není dělaný? :D
Redirect máš pro případy, kdy se člověk odhlásí, když potřebuješ po odeslání formuláře vymazat request aby nešel odeslat znovu, když máš zakázán přístup a potřebuješ přesměrovat na přihlášení atp.

Ale po update košíku udělat redirect na jiný presenter a z něj pak zpátky není ok, protože místo překreslení části stránky (košíku) a tedy jednoho requestu, který upraví košík do databáze a vrátí snippet (jednu stránku v případě neajaxového requestu) se provede uložení aktuálního stavu stránky (včetně requestu, proto store request), což nastartuje session
pak request na jinou stránku, kde se updatne košík a pak restore request, který opět nastartuje session, což je redirect a s kódem 302 zpátky na původní stránku…

Problém je, že to sice udělá restoreRequest, ale ten není klasické přesměrování, takže pokud upravíš košík, tak pomocí RestoreRequestu se stane to, že se stránka po načtení nevykreslí znova. Zavolá se tuším jen metoda startup() a ani se nebude vykreslovat šablona, protože ta je uložena v session v tom requestu…, což má za následek to, že ty změny v košíku v té action metodě se s největší pravděpodobností nepropíšou a košík bude vypadat stejně jako před updatem. Stejně tak se nepřepíšou různé změny v cookies apod., pokud nějaké uděláš.

Takže by jsi musel použít klasický redirect a ne restore request a tedy si posílat URL, kam máš přesměrovat zpátky, což zase přináší problémy s přenášením URL v URL, nebo jiné srandy, protože to se dá podstrčit jiná URL a můžu tak poslat tobě odkaz, který tě pak přesměruje na mou phishing stránku a ukradnu ti údaje atp.

Takže.. Je to správně jak píše @mbrecher … Ideálně komoponenta, která se o svý překreslování bude starat svým signálem.
Udělá se pouze 1 request bez zbytečného redirectu, nebude se zbytečně startovat session, pokud máme košík udělaný přes cookies, aby se přenášel i když se uživatel přihlásí, ušetří to spousty výkonu, protože se nemusí celá stránka ukládat a pak zase načítat, ušetří to Bandwidth, protože se bude dělat půlka requestů a na ohromně menší množství dat a v neposlední řadě je to bezpečnější a přenositelnější a programátor se méně napíše, jelikož nebude muset řešit problémy s překreslováním změn, bezpečnost atp.

EDIT
StoreRequest a RestoreRequest se hodí na případy automatického odhlášení, kdy se chceme vrátit na rozpracovanou stránku po opětovném přihlášení a to například do poloviny vyplňování formuláře a stránka se nijak nezměnila od poslední návštěvy.

Signály se hodí na překreslení části aktuální stránky. A to do toho spadá i košík. Navíc, pokud nastane situace, kdy není volán signál ajaxem, ale my potřebujeme zabránit pomocí f5 opětovnému přidání zboží například, tak signál umožňuje redirect na aktuální view velmi jednoduše a nemusíme řešit kam máme přesměrovat a odkud se provedl request.

if ($this->isAjax()) {
    $this->redrawControl('basket');
} else {
   $this->redirect('this');
}

Editoval Bulldog (13. 10. 2022 21:02)