Jak na callbacky pro filter in/out

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

Jak korektně udělat callbacky pro filtry rout? Potřebuji překládat IDčka na SLUGy a naopak. V routě mám zaregistrované callbacky na statické funkce, ale tam se potřebuji dostat k fasádě abych se dostal k datům v db. Prozatím to řeším takto neštastně:

class FoldersRouter
{
	/**
	 * @param string $slug
	 *
	 * @return int|bool
	 */
	public static function getFolderIdBySlug($slug)
	{
		// Check if slug is string...
		if ( is_numeric($slug) ) {
			// ...then convert is not necessary
			return $slug;
		}

		// Get module facade
		$folderFacade = \Nette\Environment::getService('mailboxModule.folderFacade');

		if ( $folderEntity = $folderFacade->findOneBySlug((string) $slug) ) {
			return $folderEntity->getId();
		}

		return FALSE;
	}

	/**
	 * @param int $id
	 *
	 * @return string|bool
	 */
	public static function getFolderSlugById($id)
	{
		// Check if identifier is string
		if ( is_string($id) ) {
			// ...then convert is not necessary
			return $id;
		}

		// Get module facade
		$folderFacade = \Nette\Environment::getService('mailboxModule.folderFacade');

		if ( $folderEntity = $folderFacade->findOneByIdentifier((int) $id) ) {
			return $folderEntity->getSlug();
		}

		return FALSE;
	}
}

jako korektně nahradit \Nette\Environment ?

jiri.pudil
Nette Blogger | 1029
+
0
-

Co takhle mít tyhle metody v nějaké službě, aby sis do ní mohl injectnout závislosti? Tu službu samotnou si pak injectneš do RouterFactory a callback napíšeš nestaticky.

akadlec
Člen | 1326
+
0
-

No právě že routy se registrují v ModuleExtension jako RoutesDefinition takže když se definuje callback tak toho k dispozici moc není.

class MailboxModuleExtension extends NamedExtension implements IRouterProvider
{
	public function getRoutesDefinition()
	{
		$list[] = new NetteRouteMock('//app.[!<domain [a-zA-Z0-9-]+>].[!<tld [a-zA-Z0-9-]+>]/[!<locale [a-z]{2,4}>/]mailbox[/<mailbox>]', array(
			'module'	=> 'Application',
			'presenter'	=> 'Default',
			'action'	=> 'default',
			'mailbox'	=> array(
				Route::FILTER_OUT	=> 'FoldersRouter::getFolderSlugById',
				Route::FILTER_IN	=> 'FoldersRouter::getFolderIdBySlug'
			),
			'locale'	=> array(
				Route::VALUE	=> 'en',
				'fixity'		=> Route::CONSTANT,
			)
		));
	}
}

Editoval akadlec (4. 3. 2014 9:33)

David Grudl
Nette Core | 8218
+
+4
-

Překládat v routách ID na SLUG a obráceně je nesmysl. Pokud chci používat slugy, tak prostě používám v odkazech slugy, a ne ID. Jaký má smysl dávat do odkazů ID, když je pak musím převádět? Převádění znamená hromadu neoptimálních dotazů na databázi, úplně zbytečných.

Navíc ID a slug nejsou ekvivalentní identifikátory. ID je identifikátor, který se z principu nemění. Slug se měnit může. Potom ale musím zachovat funkčnost i pro původní slugy, pro které si vytvořím další databázovou tabulku, a musím zajistit přesměrování na aktuální slug. Což ovšem není úkol pro router, nýbrž presenter.

enumag
Člen | 2118
+
0
-

Překládat v routách ID na SLUG a obráceně je nesmysl.

+1

Pokud chci používat slugy, tak prostě používám v odkazech slugy, a ne ID.

-1, když vytvářím odkaz tak nechci vědět nic o tom zda v reálné URL je ID nebo slug, chci aby mě routování přesně od těchto věcí odstínilo

Editoval enumag (4. 3. 2014 14:48)

Majkl578
Moderator | 1364
+
0
-

když vytvářím odkaz tak nechci vědět nic o tom zda v reálné URL je ID nebo slug, chci aby mě routování přesně od těchto věcí odstínilo

Souhlas.

Převádění znamená hromadu neoptimálních dotazů na databázi, úplně zbytečných.

To je velmi relativní a obecně neplatné tvrzení. Záleží totiž na implementaci, která může i nemusí mít tento zmíněný vedlejší efekt.

Potom ale musím zachovat funkčnost i pro původní slugy, pro které si vytvořím další databázovou tabulku, a musím zajistit přesměrování na aktuální slug. Což ovšem není úkol pro router, nýbrž presenter.

To přeci nyní řeší kanonizace v presenteru.

enumag
Člen | 2118
+
0
-

To přeci nyní řeší kanonizace v presenteru.

Přesně.

akadlec
Člen | 1326
+
0
-

jejda pánové, tak mě v tom děláte hokej ;) tento můj případ je zatím v ovládacím rozhraní kde není nutné zachovávat staré url tvary, jen jde o „hezké“ url. Faktem je že SLUG mám k dispozici a tak je možné jej přímo do linku házet, pak si ale zase musím poupravit trycall co mě do action* render* handle* rovnou předává objekty které hledá nad entitou podle ID.

David Grudl
Nette Core | 8218
+
0
-

enumag napsal(a):

když vytvářím odkaz tak nechci vědět nic o tom zda v reálné URL je ID nebo slug, chci aby mě routování přesně od těchto věcí odstínilo

Pak je rozumným kompromisem nepředávat ani ID, ani slug, ale rovnou entitu, ze které si routa vybere, co potřebuje.

enumag
Člen | 2118
+
0
-

Pak je rozumným kompromisem nepředávat ani ID, ani slug, ale rovnou entitu, ze které si routa vybere, co potřebuje.

Ano, přesně tak to řeším. :-)

akadlec
Člen | 1326
+
0
-

Tak předat entitu není problém protože je k dispozici, tím se zmenší load na DB při generování url. A pokud se jedná o load db při dekodování url tak tady tady nevidím problém, protože se stejnak ten prvek bude loadovat z db no ni?

Tomáš Votruba
Moderator | 1114
+
0
-

@akadlec Jak jsi toto nakonec zpracoval? Mohlo by se hodit.

akadlec
Člen | 1326
+
0
-

no abych pravdu řek tak nijak, stále tam mám statické classy.

jen bych teda doplnil co bylo uvedeno výše že by se měla rovnou předat entita…ono v podstatě i to je možnost, mě jen ten callback vyhodnotí co bylo předáno, když entita, tak se jednoduše z ní vytáhne slug a když se předalo ID tak se vytáhne entita z db a veme její slug atd…teoreticky bych se toho statického načtení služby dokázal zbavit.

Tomáš Votruba
Moderator | 1114
+
+1
-

@akadlec Pokud bys chtěl odstranit statické classy, poslal jsem PR do Flame\Modules, který umožňuje použití služeb v routách.

akadlec
Člen | 1326
+
0
-

thumbs up