Globální proměnná v presenteru II

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

Ahoj, už jsem tu jednou řešil dost podobnou věc.
https://forum.nette.org/…v-presenteru

Mám v presenteru globální proměnou, kterou si naplním v render() z parametru v URL. Resp. tu hodnotu toho parametru v URL mám jako parametr té metody

render($id)
{
    $globalni = $id
}

Pak tu globální proměnou potřebuju použít v jiné metodě toho samého presenteru, ale je prázdná. Mám neustálý pocit, jakoby globální proměnné v presenteru nefungovaly, resp. se pořád mazaly.
Ten presenter je nějak perzistentní nebo se při každém requestu vytvoří a na konci smaže???

Je případně jiné možnost jak se v presenteru dostat k parametru z URL, abych se vyhnul použití globální promenné? Prosím o polopatistické vysvětlení jak pro lamu, díky :-)

Namespace
Člen | 81
+
0
-

Jestli to dobře chápu, tak by mělo stačit:

<?php

private $globalni;

public function render($id){
 $this->globalni = $id;
}
?>
Šaman
Člen | 2666
+
+1
-

Čemu říkáš globální proměnné? Globální proměnné samozřejmě fungují. V tvé ukázce ovšem vytváříš lokální proměnnou s platností jen pro metodu render. Asi si pro začátek zkus pár pokusů s OOP, bez Nette, protože s tím tohle nesouvisí.

V tom odkazovaném přispěvku už to s Nette možná souvisí, ale bez ukázky kódu těžko říct. Jak konkrétně tam provádíš to uložím si je do $global_Id? Popiš to ale tam, ať nespamujem nesouvisející příspěvek. Protože jestli třeba zapomínáš na $this, pak je jasné, že ti to nefunguje.

Šaman
Člen | 2666
+
+1
-

Namespace napsal(a):

Jestli to dobře chápu, tak by mělo stačit:

<?php

private $globalni;

public function render($id){
 $this->globalni = $id;
}
?>

Podle toho, co chce. Technicky ano, ale pokud tu metodu chce ještě použít v jiné metodě toho samého presenteru, pak tohle nestačí, protože render je skoro poslední fáze životního cyklu presenteru. V takovém případě ať použije action, nebo startup.

icanjan
Člen | 30
+
0
-

Konkrétní použití je toto:

class HomepagePresenter extends BasePresenter
{
    public $g_leftMenuID;

    public function renderDefault($leftMenuID)
    {
        $this->g_leftMenuID = $leftMenuID;
		// dalsi kod
	}

	public function styleFormSubmitted(UI\Form $form) {
		// kod
   		$this->redirect('Homepage:', $this->g_leftMenuID);
    }
}

Po odeslání formuláře, je pak v renderDefault() parametr prázdný.

Ještě bych taky poprosil objasnit jednu věc. Já si chci prostě uložit proměnou. Proč nebo jak vůbec na to mám použít „nějakou“ action nebo startup? Já v tom se svýma "ne"znalostma nevidím vůbec žádnou spojitost.
Na ten životní cyklus presenteru jsem se právě díval, proto jsem se ptal, jestli se nějak nemaže. Nedokážu si to ale dát do souvislostí. Říkám si: vidím zobrazenou stránku, v URL mám správný parametr, tak musím mít globální proměnnou naplněnou. Ale asi to chápu úplně špatně, což?

Díky

Oli
Člen | 1215
+
0
-

Tak předně není to globální parametr. Je to proměnná třídy. V tvém případě proměnná třídy HomepagePresenter.

A je to celé o životním cyklu. Ty ten parametr nenaplníš, protože render se zavolá až uplně nakonec. Takže Už se provede i styleFormSubmitted, který tě přesměruje na Homepage:, $this->g_leftMenuID. A protože je v tu chvíli g_leftMenuID NULL, tak se do url nepromítne.

NULL je protože renderDefault se nikdy nezavolá. Zavolá se až s novým requestem, který přijme $leftMenuID jako NULL.

EDIT:// Přesuň to naplnění třídní proměnné do actionDefault

Editoval Oli (6. 7. 2015 21:31)

icanjan
Člen | 30
+
0
-

Vyzkoušel jsem to, ale nepomohlo to.

protected function actionDefault($leftMenuID)
{
    $this->g_leftMenuID = $leftMenuID;
}

A ani bych neočekával, že to pomůže. Já přece volám v styleFormSubmitted() s parametrem renderDefault a ne actionDefaul. Nebo ten parametr se dává automaticky všude?

Šaman
Člen | 2666
+
+3
-

icanjan napsal(a):

… Já přece volám v styleFormSubmitted() s parametrem renderDefault a ne actionDefaul…
Co tam voláš?


Možná by bylo nejlepší nastínit celý problém. Ne co ti nejde, ale o co se snažíš. Je málo pravděpodobné, že jsi narazil na nový problém, ale velmi pravděpodobné, že se snažíš o něco, na co dávno existují lepší řešení.


A na tu otázku, proč to v Nette najednou není vidět všechno odevšaď:

  1. Globální proměnné jsou věcí procedurálního programování. V OOP máme třídní proměnné, tak jak to máš v poslední ukázce.
  2. Jde o to, kdy tu třidní proměnnou nastavíš. Dokud se neprovede metoda, která ji nastavuje, tak nastavená není.
  3. Presenter si nastavenou property pamatuje jen do konce requestu (obecně v OOP jen po dobu života konkrétní instance objektu). Ale třeba u formulářů se ti při odeslání odešle nový request ⇒ vytvoři se nová instance presenteru. A další přesměrování, tedy nový presenter, většinou následuje po zpracování dat z formuláře. Takže je potřeba znát životní cyklus presenteru a která metoda se kdy spustí. Tohle máš ale stejné i v obyčejném procedurálním programování – odešleš formulář ⇒ zavoláš nový script (nebo stejný script znovu).
  4. Pokud chceš, aby se proměnné předávaly automaticky mezi requesty, tak hledej persistentní parametry. To je pomůcka Nette frameworku, abys nemusel ručně předávat některá nastavení (typicky třeba jazyk) v každém requestu.
icanjan
Člen | 30
+
0
-

Můj celý problém je následující:

Na hlavní stránce mám menu. Po kliknutí na menu, se přesměruje zpět na stejnou hlavní stránku, jen s jiným parametrem $leftMenuID. Podle toho $leftMenuID pak volám výběr z DB a ten na té hlavní stránce zobrazuji. Takže to menu je v podstatě jen filter (výběr/selection z z DB). Tohle mě funguje dobře.
Problém nastane, když potřebuji z té hlavní stránky volat opět tu samou hlavní stránku jinak než přes to menu. V tom okamžiku ztratím to $leftMenuID. Proto jsem si ho někam chtěl schovat, abych ho vždycky když volám tu samou hlavní stránku mohl předat jako parametr.

Tedy: uživatel kliká na menu a mě do metody

public function renderDefault($leftMenuID)
    {
    }

přijde požadované $leftMenuID, protože jsem si ho tam poslal v URL jako parametr.
Dále uživatel na stránce něco udělá a způsobí odeslání formuláře:

public function styleFormSubmitted(UI\Form $form) {
       // kod
       $this->redirect('Homepage:', $this->g_leftMenuID);
   }

Na konci odeslání toho formuláře je přesměrování zpět na stejnou hlavní stránku. Ale potřebuji po návratu znát i ten původní parametr $leftMenuID. (Odesláním toho formuláře se nesmí zrušit výběr menu.) Tak jsem si myslel, že si $leftMenuID prostě uložím a zavolám si ten redirect() s tím uloženým parametrem. Což jsem tedy pochopil, že nejde páč život presenteru je přesně opačný než jsem si myslel. Místo v době zobrazení stránky je jeho život v době před zobrazením…
Tuším tedy správně, že si ten parametr $leftMenuID budu muset místo předávání v URL strčit buď do DB nebo Session? Hledal jsem nějaké jednodušší řešení.
Děkuji

Oli
Člen | 1215
+
0
-

Přijde mě to takový divný, asi jsem to uplně nepochopil :-)

Nicméně, mělo by stačit buď formulář přesměrovat pomocí $this->presenter->redirect('this'); nebo si $this->g_leftMenuID udělat jako persistentní. A neposílat ho. Jen ho měnit v menu nebo nastavit na NULL, pokud se má vymazat.

/**
 * @persistent
 */
public $g_leftMenuID;

btw. $g_leftMenuID by nemělo být public, pokud není persistent nebo se nejedná o inject. Pokud jedná, tak naopak public být musí.

Šaman
Člen | 2666
+
0
-

icanjan napsal(a):
Dále uživatel na stránce něco udělá a způsobí odeslání formuláře:

public function styleFormSubmitted(UI\Form $form) {
       // kod
       $this->redirect('Homepage:', $this->g_leftMenuID);
   }

A zkusil jsi dump toho $this->g_leftMenuIDv metodě styleFormSubmitted? Bude NULL, protože mezi metodou render, kde sis tu hodnotu nastavil a zprazováním formuláře došlo k přesměrování. To nesouvisí s Nette, ale s HTML formuláři.
Asi bych pro tyto případy použil session, v Nette se s nimi pracuje dobře. V případě, že to g_leftMenuID má být součástí adresy, tak persistentní parametry.
Ale hlavně nezapomínej, že mezi odesláním formuláře a cílovou stránkou máš většinou tři různé instance presenteru, co si v jednom nastavíš, to samozřejmě v druhém nemáš. Buď to musíš přenášet v adrese, nebo použít session, pokud si chceš pamatovat stav aplikace.

icanjan
Člen | 30
+
0
-
$this->presenter->redirect('this');

pomohlo. Sice vůbec nechápu jak to, ale funguje mě to :-)

To Šaman: ano při odeslání formuláře byla už proměnná NULL, protože se mezi tím vymazala. Jak jste mě poučili o životnosti presenteru.
Díky za odpovědi. Já se brzo ozvu s dalším problémem :-)