Routování – vícenásobná adresa předaná do argumentu

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

Ahoj,

chci se zeptat, jaký způsobem lze do argumentu/parametru zachytit více, než jeden název oddělený lomítkem. Jde o to, že se mi adresa skládá z adresy webu, jazyka a následně odkazy na články, který můžou být zároveň kategoriemi. Tzn. teoreticky libovolná hloubka. Je nějaký způsob, jak v routě zachytit parametr jakožto pole, nebo i jako řetězec pro následné rozparsování.

Př. www.example.cz/…/html/canvas

$route[] = new Route('<language>/<id>', 'Homepage:default', Route::SECURED);

Jde o to, aby v $id pak bylo „/programovani/web/html/canvas“.

Předem děkuji za jakoukoli radu,
Martin

Filip Procházka
Moderator | 4668
+
0
-

v ideálním případě by jsi si měl udělat různé routery, které budou filtrovat příchozí požadavky, podle jednotlivých argumentů. Ale tobě bude asi stačit i tohle:

$route[] = new Route('<language>/<id .?*>', array(
	'presenter' => 'Homepage',
	'action' => 'default',
	'id' => array(
		Route::FILTER_IN = function ($id) {
			return explode('/', $id);
		},
		Route::FILTER_OUT = function ($path) {
			return implode('/', $path);
		},
	)
), Route::SECURED);

při adrese /cs/programovani/web/html/canvas

class HomepagePresenter extends BasePresenter
{
	public function renderDefault($id)
	{
		dump($id);
	}
}

získáš výsledek 'programovani', 'web', 'html', 'canvas'

bojovyletoun
Člen | 667
+
0
-

To se řešilo tady , ale psal jsem, že to nejde, protože v Route nepustí paramatry, které nejsou skalární

Filip Procházka
Moderator | 4668
+
0
-

Hmm, to jsem přehlédl, asi by to chtělo upravit a poslat pull.

Vyki
Člen | 388
+
0
-

Já to dělám následovně. Z databáze si vezmu strom katalogu. Ten si seřadím, aplikuji na něj svoje filtry, ale to není podstatné. Podstatné je že dostanu pole.

<?php
	$katalog = array(
		1 =>  'katalog/knihy/php/1001-triku-pro-php',
		3 =>  'katalog/knihy',
		45 => 'katalog/knihy/php',
		12 => 'katalog/test'
	);
?>

Toto pole si uložím do cache – jednou bude klíčem id, podruhé bude klíčem kategorie.

<?php
	$cache = Environment::getCache('Route.Katalog');

	$cache->save('filterIn', $katalog, array(
                Cache::TAGS => array('route#katalog')
        ));

        $cache->save('filterOut', array_flip($katalog), array(
        	Cache::TAGS => array('route#katalog')
        ));
?>

O routování se starám následovně.

<?php

	$cache = Environment::getCache('Route.Katalog');

	Route::$styles['#katalog'] = array(
        	Route::PATTERN => '.*',
       		Route::FILTER_IN => function($s) use ($cache){

                	if(substr($s, -1) === '/') $s = substr($s, 0, -1);

                	$table = $cache['filterIn'];

                	if(isset($table[$s])) return $table[$s];

                	return NULL;
        	},
        	Route::FILTER_OUT => function($id) use ($cache){

                	$table = $cache['filterOut'];

                	if(isset($table[$id])) return $table[$id];

			return NULL;
        	}
	);

	$router[] = new Route('<id #katalog>', array(
        	'presenter' => 'Katalog:Default',
        	'action' => 'default',
	));
?>

Demonstruji na tom jak to mám udělané já, ale tento kód jsem netestoval. Ve svojí aplikaci to mám implementováno trochu komplikovaněji, tak snad to bude z tohoto jasné.

Edit: Ještě doplním, že velkou nevýhodou tohoto řešení, je držet cache aktualizovanou. Ve finále to zas takový problém není. V modelu si na metody update a delete musíš navěsit callbacky, které ti pozmění i pole v té cache pro routování.

Editoval Vyki (25. 2. 2011 14:29)

Inferi
Člen | 18
+
0
-

Děkuji za pomoc,
ještě jsem prohledával fórum a našel tento příspěvek, který mě osobně funguje. Nicméně doufal jsem v jednodušší řešení s příchodem Nette 2.