Cool URL, nazov namiesto id

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

Mam clanky, ale v url odkazoch by bolo pekne, keby je url clanku napr clanok/lesy namiesto clanok/123.
Hlasi ale chybu druhu „missing template lesy.latte“. Ako to spravit, aby atribut bral ako atribut a nie nazov metody a nasledne sablony?

docky
Člen | 59
+
0
-

ahoj, dej si například functionRenderArticle($slug) a podle toho si uprav i routu, pak budeš mít šablonu article.latte

router

$router[] = new Route('clanok/<slug>', [
			'presenter' => 'Front:Articles',
			'action' => 'article',
			'slug' => [
				Route::FILTER_OUT => 'Nette\Utils\Strings::webalize',
			],
		]);

něco takového asi

Editoval docky (20. 6. 2016 19:00)

Machy8
Člen | 59
+
+3
-

Pokud to dobře chápu a chceš mít místo id v url třeba název článku, tak budeš potřebovat upravit router

...
public $articlesModel;

// Pomocí DI získáš ArticlesModel
public function __construct(ArticlesModel $articlesModel)
{
	$this->articlesModel = $articlesModel;
}

// Z createRouter odebereš static
public function createRouter()
{
	$router = new RouteList;
	$router[] = new Route('clanok/<id>', array(
		'presenter' => 'Articles',
		'action' => 'show',
		'id' => array(
			Route::FILTER_IN => [$this->articlesModel, 'getIdByUrl'],
			Route::FILTER_OUT => [$this->articlesModel, 'getUrlById']
		)
	));
}

Aby tohle šlo, musíš odstranit statickou routu a upravit konfig

services:
	- App\RouterFactory
	router: @App\RouterFactory::createRouter()

V modelu to pak bude vypadat takto

public function getUrlById (int $id)
{
  // Id článku je 2 => url = lesy
  // Vrácení předem vytvořené url | titulek článku upravený přez Nette\Utils\Strings::webalize
}

public function getIdByUrl (string $url)
{
  // Url je například lesy => id článku = 2
  // Získání id článku podle url
}

Odkaz na transformace a překlady.

Editoval Machy8 (20. 6. 2016 23:25)

ondrej1
Člen | 13
+
0
-

Diky obidvom, pomohlo a uz mi to funguje. Upravil som routu, ale bez filtrov, url clanku mam v databaze, je tam atribut s diakritikou nazov aj atribut url nazvu (webalize), teda odkazy uz funguji(vdaka upravenej route) a temu vyhlada podla url v databaze, s id ani netreba pracovat.

Routa je jednoducho

$router[] = new Route('clanok/<url>', 'Clanok:default');

a presenter

renderDefault($url)

Dakujem
(snad to nie je nejaky prasacky kod)

Editoval ondrej1 (20. 6. 2016 23:48)

Jiří Nápravník
Člen | 710
+
+1
-

Neni to prasacky, s filtry je problem, protoze to co je vyse, to pri kazdem tvoreni saha do databaze a to muze pri vice navstevach delat celkem problemy.

Btw tu url muzes menit? pokud ano, pak doporucuji tam to id ponechat – treba mit adresu /lesy-1 – protoze pokud ti nekdo zmeni adresu, tak pak se lidi co uz na to odkazovali nikam nedostanou. Podle id ty pak muzes dohledat a nasmerovat na nvoou url adresu… (no anebo samozrejme muzes ukldat vsechny zmeny url:)

ondrej1
Člen | 13
+
0
-

Nie, url je navzdy nemenna.
Inak ked byva v adrese na konci aj id clanku, akym sposobom sa z adresy id vybera?
explode na pomlcku ci nieco ine?

CZechBoY
Člen | 3608
+
0
-

regulární výraz viz. tvorba rout

Machy8
Člen | 59
+
0
-

@JiříNápravník je to možná hloupej dotaz, ale jak to tedy řešit lépe, než dotazy do databáze? Ptám se, protože povětšinou co jsem viděl i odpovědi na fóru, tak se to takto řešilo.

Editoval Machy8 (21. 6. 2016 23:11)

Jiří Nápravník
Člen | 710
+
+3
-

Machy8 napsal(a):

@JiříNápravník je to možná hloupej dotaz, ale jak to tedy řešit lépe, než dotazy do databáze? Ptám se, protože povětšinou co jsem viděl i odpovědi na fóru, tak se to takto řešilo.

V podstatě jak to tady zmínil @ondrej1

Routa takhle:

	$router[] = new Route('clanok/<url>', 'Clanok:default');

url máš v databázi a až v presenteru si vytáhneš článek z databáze. Problém filtru v routeru je, že se volá databáze při každém skládání a matchování. Což nevadí tolik, pokud to jsou malé tabulky apod. Ale pokud máš tisíce článků a děláš větší výpisy třeba v kategorii, tak je to problém.

Jan Suchánek
Člen | 404
+
0
-

Skládání a matchovat můžeš zrychlit pomocí cache, ale i tak je rozumnější se tomu vyhnout a url předávat a tahat v Presenteru jak sem snad poochopil @JiříNápravník.

  1. řešit v Routě filtrem s Cache
  2. nechávat v šabloně jen Slug a v Presenteru kontrolovat platnost
  3. nechávat v šabloně Slug i Id

Každopádně nešlo by šabloně přenechávat ID a až nakonec udělat hromadný replace všech Url?
Otázka, ale je zda je to výhodné a vůbec v čem?

Editoval Jan Suchánek (22. 6. 2016 16:34)

Felix
Nette Core | 1189
+
0
-

@JanSuchánek Jak myslis to Každopádně nešlo by šabloně přenechávat ID a až nakonec udělat hromadný replace všech Url?? :-)

Jan Suchánek
Člen | 404
+
0
-

Felix napsal(a):

@JanSuchánek Jak myslis to Každopádně nešlo by šabloně přenechávat ID a až nakonec udělat hromadný replace všech Url?? :-)

Myslím tím, že před Rendrem šablony provést finální úpravu všech Url najednou, neb přepisovat všechny Url po jednom je totální krávovina, ale tím asi jdu proti smyslu celého počínání Nette Route, co jsem slyšel na školení tak přepisovat z id na slug je zbytečná zátěž, teda tak jsem to chápal.

Proč přepisovat ID pomocí filtru na Slug? A není lepší tedy v Latte předat jen Slug.

<a n:href="Presenter:Action, slug => $entity->getSlug()">Example Link</a>

a mnohem rychleji, vyhnout se vůbec Routě

<a href="{$entity->getSlug()}">Example Link</a>

a následně v Presenteru řešit jejich platnost a případné přesměrování

Editoval Jan Suchánek (22. 6. 2016 17:54)