routování podle konkrétního presenteru

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

Jde nějak routovat podle presenteru? Myslím tím, mít někde nahoře routu, která se provede jen když je aktivní nějaký presenter, např PagePresenter. Pokud není aktivní PagePresenter, tak se routa neprovede i když maska vyhovuje.

Např: Teď mám 2 routy a ty fungujou:

$pageRoute = new PageRoute('<id>', array(
	'presenter' => 'pages',
	'action' => 'detail',
	...
));
$router[] = $pageRoute;

$router[] = new Route('<presenter>/[<action=default>]', array(
	...
));

Potřeboval bych mít ale v první routě jeden nepovinný parametr, něco jako:

$pageRoute = new PageRoute('[<parent>]<id>', array(
	'presenter' => 'pages',
	'action' => 'detail',
	...
));
$router[] = $pageRoute;

$router[] = new Route('<presenter>/[<action=default>]', array(
	...
));

Pokud to udělám takhle, tak mě všechny dotazy spadnou na první routu, protože má nějaké dva parametry. Já bych ale potřeboval aby se první routa vykonala jen, když bude presenter Pages. Zároveň, ale nechci mít název presenteru v URL.

Lze to nějak udělat, nebo mám blbě návrh rout?
Díky.

BigCharlie
Člen | 283
+
0
-

V tom druhém případě to není možné napsat takhle obecně. Které routě by podle tebe vyhověla adresa http://tvuj.web/cokoliv?

Nette bere vždy první routu, která vyhoví (ostatně v route debuggeru máš určitě u té druhé routy poznámku matched – may). Jak má poznat, kdy se jedná o id z první routy, nebo presenter z druhé routy?

V takovémhle případě buď musíš udělat specifičtější routu (tedy doplnit Pages do routy), nebo si napsat vlastní router.

Lepší řešení neznám, třeba mě někdo opraví…

Oli
Člen | 1215
+
0
-

No právě, na to se ptám. Jestli jde nějak říct, že v tý první routě ty dva parametry jsou parametry a ne název routy nebo akce.

Jestli existuje něco jako, já nevím, například:

$pageRoute = new PageRoute('<id>', array(
    'presenter' => 'pages',
    'action' => 'detail',
    ...
), PagePresenter);

Prostě, že by se podivalo do ty routy jen, kdyby se mel vykonat PagePresenter, jinak jet dal… Asi to je takhle blbost, jen se ptam, jstli nahodou něco takovýho neexistuje :-)

Vlastní router jsem si napsal podle přednášky Honzy Smitka:

class PageRoute extends \Nette\Application\Routers\Route
{

	/** @var \PageModel */
	private $page;

	public function match(\Nette\Http\IRequest $httpRequest)
	{
		/**
		 * @var \Nette\Application\Request
		 */
		$appRequest = parent::match($httpRequest);
		if ($appRequest != null && !is_numeric($appRequest->parameters['id']))
		{
			$page = $this->page->getBySlug($appRequest->parameters['id']);
			if (!$page)
			{
				return null;
			}
			$params = $appRequest->parameters;
			$params['id'] = $page->id;
			$appRequest->parameters = $params;
		}

		return $appRequest;
	}
}

Když to nějak rozšířím, tak tam můžu dostat ty dva parametry, který budou vidět v url, ale nebudou v masce? Nebo jsi to myslel jinak s tím napsáním vlastního routeru?

V podstatě chci výstup:

JakykoliPresenter:NejakaAkce
neco.cz/jakykoliPresenter/nejakaAkce // Standardní chování, pokud není presenter PagePresenter

PagePresenter/detail $dite
neco.cz/slug-ditete

PagePresenter/detail $rodic, $dite
neco.cz/slug-rodice/slug-ditete

Je to vubec mozny?
Diky

Tori
Člen | 32
+
0
-

Jestli jde nějak říct, že v tý první routě ty dva parametry jsou parametry a ne název routy nebo akce

Kolik je těch ostatních presenterů? Možná by to šlo takhle:

// nejdřív vyjmenovat všechny ostatní presentery
$router[] = new Route('<presenter x|y|z>/[<action=default>]');

// všechno ostatní spadne presenteru Page
$router[] = new Route('<parent>[/<id>]', array(
	'presenter' => 'Page',
	'action' => 'default',
));
llsm
Člen | 121
+
0
-

A co takhle bez pouziti? (psano z hlavy)

<?php

 //Vsechno, co je na strance Page:Detail, child je povinny, parent volitelny parametr
 $router[] = new Route('[<parent>/]<child>', array(
	'presenter' => 'Page',
	'action' => 'detail',
	'child' => array(
		//Filtry pro prekladani slugu
		Route::FILTER_IN => callback('SlugToID'),
                Route::FILTER_OUT => callback('IDToSlug'),
	),
        'parent' => array(
		//Filtry pro prekladani slugu
        	Route::FILTER_IN => callback('ParentSlugToID'),
                Route::FILTER_OUT => callback('ParentIDToSlug'),
	),
 ));

 // Co nevyhovi predchozim routam, spadne do obecne
 $router[] = new Route('<presenter>/[<action=default>]', array(
	...
 ));
?>
Oli
Člen | 1215
+
0
-

Tori: Díky, tohle mě taky napadlo, ale přijde mě to jako se drbat pravou rukou za levým uchem :-)

llsm: Díky! Tohle je přesně ono. Nenapadlo mě, že když nastavím výstupní a vstupní filter, tak to tím i takhle omezím. :-)