URL generator: TODO

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

K vytvoření odkazu je nyní potřeba presenter. Pokud ale chci generovat odkaz v cli nebo v cronovém scriptu například pro odesílaný mail, musím adresu skládat ručně.

Komplikaci to přináší obecně i v modelech, kde pokud chci zjistit url adresu, musím postupovat zhruba takto:

class MujSuperModel
{
	public function getItemInfo(Item $item, Presenter $presenter)
	{
		$link = $presenter->link('Link:default', ['id' => $item->getId()]);
		return ['name' => $item->getName(), 'link' => $link];
	}
}

Bylo by tedy dobré vytváření odkazů separovat do speciální třídy, která by byla dostupná v DI kontejneru jako služba.

Nemáte někdo chuť to implementovat?

redhead
Člen | 1313
+
0
-

Ono by to s tím chtělo refaktorovat celý Presenter. Už jsem o tom přemýšlel a přesně na tohle jsem také narazil. Chtělo by to nějaký Linker :) Bohužel nemám na to moc čas, ale něco započnuté už mám.

Editoval redhead (13. 3. 2013 21:34)

Filip Procházka
Moderator | 4668
+
0
-

Pokud chceš generovat url v CLI, můžeš použít Kdyby/Console, které mimo jiné tohle řeší :)

Editoval Filip Procházka (13. 3. 2013 21:46)

Majkl578
Moderator | 1364
+
0
-

+1, Hosiplanovo řešení je jen hnusný (ač jediný schůdný) hack.

redhead
Člen | 1313
+
0
-

Nehledě na to, že by se konečně mohlo optimalizovat vytváření linků, což je jeden z největších zbržďovačů.

Caine
Člen | 216
+
0
-

@Honza Marek +1

David Grudl
Nette Core | 8228
+
0
-

Ke generování odkazů slouží $router->constructUrl(), kterému se předá Nette\Application\Request a souřasné URL.

Honza Marek
Člen | 1664
+
0
-

Pak by to tedy chtělo z presenteru vyčlenit „ApplicationRequestFactory“, aby třeba v šablonách makra link nepotřebovaly presenter. Vim, že se podle něj pozná, co to je třeba odkaz na this, ale to by se dalo nahradit nějakým textovým scope – Front:Homepage:default-komponenta-podkomponenta. Pokud by scope nebyl k dispozici, bylo by potřeba do „url generatoru“ (který by vznikl jako malinká třída spojující router a ApplicationRequestFactory) dát v parametru absolutní cestu.

David Grudl
Nette Core | 8228
+
0
-

To by bylo fajn.

pawouk
Člen | 172
+
0
-

+1 už dloho toužím po Třídě která se stará o generování url.

Editoval pawouk (14. 3. 2013 8:00)

Panda
Člen | 569
+
0
-

Přesně nad něčím ve stylu ApplicationRequestFactory jsem už přemýšlel a dokonce jsem pro vlastní aplikaci něco základního připravoval, tak zkusím v následujícím týdnu připravit fork Nette na otestování.

Panda
Člen | 569
+
0
-

Prozatím jsem vyčlenil RequestFactory, poté ještě vytvořím LinkFactory – název se mi moc nelíbí, jak byste to pojmenovali vy?

Aktuální stav je k nahlédnutí v mém forku Nette, větev app-request-factory: https://github.com/…uest-factory
Testy: https://travis-ci.org/jsmitka/nette

Patrik Votoček
Člen | 2221
+
0
-

Panda napsal(a):

… poté ještě vytvořím LinkFactory – název se mi moc nelíbí, jak byste to pojmenovali vy?

LinkGenerator?

Filip Procházka
Moderator | 4668
+
0
-

UrlConstructor podle Routeru :)

enumag
Člen | 2118
+
0
-

Osobně proti LinkFactory nic nemám, ale pokud něco jiného tak bych předchozí nápady zkombinoval na UrlGenerator.

pawouk
Člen | 172
+
0
-

+1 pro UrlGenerátor

Panda
Člen | 569
+
0
-

Prozatím jsem použil LinkGenerator, ale asi to přejmenuji na UrlGenerator. Díky všem za názory. :-)

Ještě jsem narazil na jeden drobný detail – pro vygenerování URL je potřeba mít k dispozici současné URL. To je v pohodě při běhu na webu, ale bude dělat problémy při použití například v konzoli – vygenerované URL samozřejmě nebude odpovídat.

Řešení mě napadla dvě:

  1. Pštrosí algoritmus – strčit hlavu do písku a neřešit to s tím, že bude na programátorovi, aby dodal programově správné referenční URL (= zavolá si setRefUrl() nad instancí URL generatoru). To detailně zdokumentovat.
  2. Konfigurace referenčního URL v sekci Nette – pokud kontejner při vytváření služby detekuje, že nejsou k dispozici $_SERVER['HTTP_HOST'] ani $_SERVER['SERVER_NAME'], použije referenční URL nastavené v konfiguračním souboru. Když URL nebude nastavené – bude se chovat jako v prvním případě.

Trošku problém by mohl být s tím, že router na první pohled vyžaduje cestu ke skriptu (např. http://example.com/subdir/index.php) a asi se to bude chovat podivně, pokud zadám třeba jen http://example.com/subdir – budu muset vyzkoušet, jak se jednotlivé routery chovají.

Filip Procházka
Moderator | 4668
+
0
-

Já to řeším takto.

Panda
Člen | 569
+
0
-

Přemýšlím, jestli je úplně vhodný nápad to URL podvrhovat už v Http\RequestFactoryLinkGenerator vůbec nepotřebuje celý request, stačí mu jen URL, takže zatím fallbackRefUrl vyhodnocuji při vytváření služby. A URS se nastavuje v konfiguráku.

Další na řadě bude integrace do šablon, aby bylo možné makro {link} používat jen s instancí LinkGeneratoru a nebyla potřeba instance komponenty/presenteru.

Editoval Panda (19. 3. 2013 23:47)

Panda
Člen | 569
+
0
-

Makra {link} a {plink} jdou používat i bez komponenty/presenteru, stačí nastavit šabloně proměnnou $_linkGenerator a nenastavit $_control/$_presenter. Pokud bude komponenta/presenter nastavená, použije se (například kvůli makru {ifCurrent}). Díky tomu by mělo být vše zpětně kompatibilní.

Možná ještě vrátím zpátky makro {plink} tak, aby používalo jen presenter a nikoliv $_linkGenerator – pokud budu chtít používat odkazy bez presenteru, dává mi větší smysl všechno hnát přes {link}. Co myslíte?

Ještě přemýšlím, zda nepřidat nastavení proměnné $_linkGenerator do API. Takové

$template->setLinkGenerator($linkGen);

by se mi celkem líbilo. Navíc se bude $_linkGenerator používat jen při samostatném použití, pokud je šablona vázaná na komponentu či presenter, nemá jeho nastavování smysl, takže by to bylo přehlednější.

hrach
Člen | 1838
+
0
-

Je treba zasadne od sebe odlisit dve veci. Latte a Templates. Mozna by nebylo od veci, kdyby generovani linku se provadelo pres helper.

  • Latte by compilovalo {link } do volani helperu na template
  • Nebylo by treba zadne nove api
  • Presenter by registroval do helperu plink sebe, do linku linkGenerator
  • programator bez presenteru by si registroval jen link helper
  • jedinou otazkou zustava, co pak s ifCurrent

Editoval hrach (21. 3. 2013 10:26)

Panda
Člen | 569
+
0
-

Použití helperu je určitě dobrý nápad, zmíněné makro {ifCurrent} by bylo asi možné vyřešit použitím dalšího helperu. Jen by to byl takový helper nehelper, protože například helper pro link by bylo možné použít i bez makra ({$destination|link}), zatímco tento by vracel jen true/false.

Ještě drobnost: jak helpery pojmenovat? Použít rovnou link a plink, kde hrozí, že už někdo helper s takovým názvem bude používat, nebo je prefixovat podtržítkem: _link, _plink? Nette žádné takové interní helpery nemá, takže si nejsem jistý, jakou cestou jít. Lepší by bylo asi _link

Každopádně helper asi zkusím do večera implementovat.

Panda
Člen | 569
+
0
-

Tak jsem se konečně dostal k implementaci helperu. Celkově je to fajn, jen mi docela vadí, že je to potenciálně zpětně nekompatibilní.

Používá někdo úplně vlastní createTemplate() v presenteru nebo komponentách, kdy nevolá rodičovskou metodu?

Honza Marek
Člen | 1664
+
0
-

Jestli mi projde tohle, tak se stejně budou šablony vyrábět úplně jinak (i když metody createTemplate zůstanou).

Budry
Člen | 88
+
0
-

Pokaždé, kvůli možnosti registrovat helpery do šablon v konfigu

Panda
Člen | 569
+
0
-

Důležitá je ta část „nevolá rodičovskou metodu“, tzn. není tam parent::createTemplate(). popř. Control::createTemplate(). K registraci helperů ti volání metody předka nevadí.

Jde mi o to, jestli může existovat nějaký opodstatněný scénář, kdy původní metoda z Nette není volána.

Budry
Člen | 88
+
0
-

Eh, omlouvám se
rodiče nevolám, ale je pravda že můžu a nevadí to…