Vygenerovat link ze SystemContaineru

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

Když jsem v Presenteru, napíšu:

class BasePresenter
{
  function renderDefault()
  {
    $link = $this->link("Hello:world");
  }
}

Dejme tomu, že ale v presenteru napíšu:

class BasePresenter
{
  function renderDefault()
  {
    $link = foo($this->context);
  }
}

function foo($context)
{
  return ???
}

Co mám zapsat místo otazníčků abych dostal link? Díky.

Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Asi nic :). Linky generuje presenter, ne SystemContainer.

Felix
Nette Core | 1247
+
0
-

Ale velmi nedoporucuju! Je to spatny navrh!

function foo($context)
{
  return $context->application->presenter->link(...);
}

Editoval Felix (2. 4. 2013 17:30)

josef.sabl
Člen | 153
+
0
-

Felix napsal(a):

Ale velmi nedoporucuju! Je to spatny navrh!

function foo($context)
{
  return $context->application->presenter->link(...);
}

Díky, tyhle odpovědi jsem samozřejmě čekal (špatný návrh) :o)

echo
Člen | 134
+
0
-

Tento „špatný návrh“ používá interně samo Nette. :o) Viz. https://api.nette.org/…ent.php.html#318

Nox
Člen | 378
+
0
-

Proč tam máte celý kontejner, když v tom pak hledáte jen presenter, nestačil by rovnou presenter? Pak byste mohli mít typehint na PresenterComponent: pak tam projde cokoli co umí PresenterComponent::link() a funkce se nemusí rýpat v kontejneru a hledat co použít.

Další možnost (imho lepší než $context, horší jak PresenterComponent):

<?php
$presenter = $this;
$linkBuilder = function($destination, $args = array()) use($presenter) {
    return $presenter->link($destination, $args);
};

foo($linkBuilder);

// php5.4+
$linkBuilder = function($destination, $args = array()) {
    return $this->link($destination, $args);
};
?>
Filip Procházka
Moderator | 4668
+
0
-

echo napsal(a):

Tento „špatný návrh“ používá interně samo Nette. :o) Viz. https://api.nette.org/…ent.php.html#318

Na tom nic špatného není.

Felix
Nette Core | 1247
+
0
-

echo napsal(a):

Tento „špatný návrh“ používá interně samo Nette. :o) Viz. https://api.nette.org/…ent.php.html#318

To je ale neco jinyho. Ne ze jdu pres Container → App → Controller.

echo
Člen | 134
+
0
-

Felix napsal(a):

echo napsal(a):

Tento „špatný návrh“ používá interně samo Nette. :o) Viz. https://api.nette.org/…ent.php.html#318

To je ale neco jinyho. Ne ze jdu pres Container → App → Controller.

Mi to přijde principiélně to samý. Akorát jde o hierarchii komponent a ne o hierarchii služeb (konteiner). viz. tam to $this->lookup(‚…UI\Presenter‘).

Obojí ti to vrátí pokaždé jinou třídu/presenter (v závislosti na akci). IMHO nic špatného na tom není.

Editoval echo (3. 4. 2013 14:40)

josef.sabl
Člen | 153
+
0
-

Jak byste mně, Nette začátečníkovi, resp. uživateli Nette střev neznalého, popsali, co je to container a proč je špatně, abych jen na základě jeho dostupnosti měl mít možnost vygenerovat link podle routeru, který je v bootstrapu konfigurován na úrovni právě tohoto containeru:

$container->router[] = new Route('index.php', 'Homepage:default', Route::ONE_WAY);
$container->router[] = new Route('<presenter>/<action>[/<id>]', 'Homepage:default');

Díky

PS: Nejsem hledač nejkratší cesty. Kdybych byl, tak tam prdnu <a href='/hello/world'> a je vymalováno :o)

Editoval josef.sabl (3. 4. 2013 15:22)

bazo
Člen | 620
+
0
-

a preco chces vobec v bootstrape tvorit odkazy?

josef.sabl
Člen | 153
+
0
-

bazo napsal(a):

a preco chces vobec v bootstrape tvorit odkazy?

V bootstrapu netvořím odkazy. V bootstrapu na úrovni containeru definuju routy. Proto je mi divné, že na úrovni containeru později nesmím router použít k vygenerování linku. Ale jak říkám, nejsem žádný nette odborník a rád se nechám vyvést z omylu.

bazo
Člen | 620
+
0
-

tak sa opytam inak, co vlastne chces dosiahnut?

josef.sabl
Člen | 153
+
0
-

bazo napsal(a):

tak sa opytam inak, co vlastne chces dosiahnut?

Odpovědi na mou otázku :-)) Co je container a proč je špatně, aby tvořil odkazy. Nic nerozporuju, ale chci to nějak víc pochopit.

To, co jsem v aplikaci potřeboval, jsem vyřešil. Dotaz byl: mám context, jak získám odkaz.
Ale změnilo se to v akademickou debatu, tak se akademicky ptám.

Editoval josef.sabl (3. 4. 2013 16:13)

Nox
Člen | 378
+
0
-

„Žán, podejte mi to piáno. Mám na něm doutník.“

Každá část aplikace by měla mít závislostí tak akorát aby nedělala co nemá dělat ale zase nebyla příliš svázaná. Mělo by být vidět jaké a pokud jde z toho odhadnout proč, tím líp. Čím menší množství závislostí, tím jednodušeji se bude upravovat, vytvářet mocky atd.

Pokud část aplikace potřebuje něco co ji vytvoří odkaz, pak je nejvýhodnější předat to a jen to, co vytváří odkaz. Ta část málokdy potřebuješ přesně ten kontejner, celý kontejner.

Jednodušší potom bude i znovupoužitelnost: pokud chceš použít třídu X která má závislost na Y, je pravděpodobné, že cílová aplikace bude taky disponovat něčím jako Y. Ale pokud to ta X příjmá obalené v chuchvalci nějakých dalších irelevantních objektů, bude to potřeba více upravovat.

Dále si vezmi, že tam budeš chtít třeba předat jinou instanci (nemusí být jen u testů). U kontejneru budeš muset vytvoří nový kontejner, do něj dát sekci application, do ní presenter; přitom by stačilo dát prostě ten presenter.

josef.sabl
Člen | 153
+
0
-

Nox napsal(a):

„Žán, podejte mi to piáno. Mám na něm doutník.“

Každá část aplikace by měla mít závislostí tak akorát aby nedělala co nemá dělat ale zase nebyla příliš svázaná. Mělo by být vidět jaké a pokud jde z toho odhadnout proč, tím líp. Čím menší množství závislostí, tím jednodušeji se bude upravovat, vytvářet mocky atd.

Pokud část aplikace potřebuje něco co ji vytvoří odkaz, pak je nejvýhodnější předat to a jen to, co vytváří odkaz. Ta část málokdy potřebuješ přesně ten kontejner, celý kontejner.

Jednodušší potom bude i znovupoužitelnost: pokud chceš použít třídu X která má závislost na Y, je pravděpodobné, že cílová aplikace bude taky disponovat něčím jako Y. Ale pokud to ta X příjmá obalené v chuchvalci nějakých dalších irelevantních objektů, bude to potřeba více upravovat.

Dále si vezmi, že tam budeš chtít třeba předat jinou instanci (nemusí být jen u testů). U kontejneru budeš muset vytvoří nový kontejner, do něj dát sekci application, do ní presenter; přitom by stačilo dát prostě ten presenter.

Díky za piáno, já ale nechtěl ani ten doutník :-) To, co popisuješ je DI. Vím, co je DI a souhlasím, že je to dobrá věc (nejsem bojovník proti DI :-).

A omlouvám se, jestli jsem se kohokoli dotknul.

Mám jen zmatek v tom, jakou roli by měl mít presenter a jakou roli by měl mít container. Pro mě je context (container) taková ta věc, co tam jsou různý zajímavý věci a presenter je pro mě objekt, který vyřizuje aktuální požadavek. Application jsem nějak vůbec nepobral :)

Když to vezmu z mého pohledu (který je zcela jistě pokřivený a snažím se ho tady narovnat), tak link by měla tvořit šablona, která jeho informační hodnotě zapsané nějakým identifikátorem anebo polem, přiřadí konkrétní formát/podobu.

Budu teda docela konkrétní: Ve zmíněné aplikaci je služba (Cron), která se pravidelně podívá do konfigurace, kde je seznam workerů, kteří se mají v daný okamžik spustit. Např. rozeslání newsletterů zákazníkům.

Každý worker je nějaká třída, která dědí toto:

abstract class Worker
{
	protected $context;

	public function __construct(\Nette\DI\Container $container)
	{
		$this->context = $container;
	}

	abstract function execute();
}

A pak mám třídu NewsletterSender, která posílá maily, jejichž obsahem jsou mimo jiné odkazy. A jsme doma, mám kontext, potřebuju odkaz. Co je tedy špatně?

David Matějka
Moderator | 6445
+
0
-

„jednoduche“ generovani linku zatim jinak nez pres presenter nejde (resi se to tady https://forum.nette.org/…nerator-todo takze nekdy v budoucnu by mela byt sluzba na tvorbu odkazu..)
zatim jsou tedy 2 moznosti: bud se nejak dostat k presenteru
nebo (a to bude lepsi) pouzit router a metodu constructUrl (viz https://api.nette.org/…IRouter.html#…)

bazo
Člen | 620
+
0
-

tak staci hned povedat, ze chces tvorit odkazy mimo sablon a presenterov. potom by sa tu nezvrhla ziadna akademicka debata.

slo by to nejak takto

function link(IRouter $router, \Nette\Http\UrlScript $url){
    $params = [...];
    $appRequest = new \Nette\Application\Request($destination, \Nette\Http\IRequest::GET, $params);
    $link = $router->constructUrl($appRequest, $url);
}
josef.sabl
Člen | 153
+
0
-

matej21 napsal(a):

„jednoduche“ generovani linku zatim jinak nez pres presenter nejde (resi se to tady https://forum.nette.org/…nerator-todo takze nekdy v budoucnu by mela byt sluzba na tvorbu odkazu..)
zatim jsou tedy 2 moznosti: bud se nejak dostat k presenteru
nebo (a to bude lepsi) pouzit router a metodu constructUrl (viz https://api.nette.org/…IRouter.html#…)

Ach, dokonalá odpověď, díky ti!

josef.sabl
Člen | 153
+
0
-

bazo napsal(a):

tak staci hned povedat, ze chces tvorit odkazy mimo sablon a presenterov. potom by sa tu nezvrhla ziadna akademicka debata.

slo by to nejak takto

function link(IRouter $router, \Nette\Http\UrlScript $url){
    $params = [...];
    $appRequest = new \Nette\Application\Request($destination, \Nette\Http\IRequest::GET, $params);
    $link = $router->constructUrl($appRequest, $url);
}

Díky i tobě za ukázku, jak použít router.

PS: Akademické debaty jsou prima, člověk se něco doví ;-)

Editoval josef.sabl (3. 4. 2013 17:25)