komponenty – subpattern name is too long (maximum 32 characters)
- Zax
- Člen | 370
Zdravím,
tvořím web složený z komponent (přišlo mi to jako dobrý nápad…) a mám problém s routováním. Hluboko v komponentovém stromě mám stránkovač, kterému chci nastavit hezké url.
Zkusil jsem toto:
$router[] = new Routers\Route('administrace/skupiny[/<rolesPanel-rolesList-paginator-page>]', 'Web:Back:Users:roles');
Nette vyhodí výjimku:
Nette\Utils\RegexpException
preg_match(): Compilation failed: subpattern name is too long (maximum
32 characters) at offset 69 in pattern:
#administrace/skupiny(?:/(?P<rolesPanel___rolesList___paginator___page>(?U)[^/]+))?/?\z#Aiu
Jde to nějak chytře obejít?
Persistentní parametry (nebo jakoukoliv jinou režii navíc) v presenterech bych rád vyloučil, pokud možno.
Děkuji.
Editoval Zax (12. 5. 2014 18:24)
- Jan Tvrdík
- Nette guru | 2595
Ano, jde.
$router[] = new Routers\Route('administrace/skupiny[/<paginator-page>]', [
'presenter' => 'Web:Back:Users',
'action' => 'roles',
NULL => [
Routers\Route::FILTER_IN => function ($params) {
if (isset($params['paginator-page']) {
$params['rolesPanel-rolesList-paginator-page'] = $params[''];
unset($params['paginator-page']);
}
return $params;
},
Routers\Route::FILTER_OUT => function ($params) {
if (isset($params['rolesPanel-rolesList-paginator-page']) {
$params['paginator-page'] = $params['rolesPanel-rolesList-paginator-page'];
unset($params['paginator-page']);
}
return $params;
},
]
]);
- Zax
- Člen | 370
Přidal jsem si do továrny tuhle metodu
protected function createAliases($aliases) {
if(func_num_args() > 1)
$aliases = array($aliases => func_get_arg(1));
return array(
Routers\Route::FILTER_IN => function($params) use ($aliases) {
foreach($aliases as $alias => $fullName) {
if(isset($params[$alias])) {
$params[$fullName] = $params[$alias];
unset($params[$alias]);
}
}
return $params;
},
Routers\Route::FILTER_OUT => function($params) use ($aliases) {
foreach($aliases as $alias => $fullName) {
if(isset($params[$fullName])) {
$params[$alias] = $params[$fullName];
unset($params[$fullName]);
}
}
return $params;
}
);
}
a volám takto:
$router[] = new Routers\Route('administrace/skupiny[/<page>]', array(
'presenter' => 'Web:Back:Users',
'action' => 'roles',
NULL => $this->createAliases(array('page'=> 'rolesPanel-rolesList-paginator-page'))
// nebo createAliases('page', 'rolesPanel-rolesList-paginator-page') pro lenochy
));
Třeba se to bude někomu hodit ;-)
- enumag
- Člen | 2118
Spíše by bylo lepší upravit to přímo v nette aby router dlouhé parametry nepoužíval jako subpattern name v regexpu ale třeba je zahashoval pomocí md5 nebo vytvářel aliasy automaticky. Tohle chování je imho bug a neměly by být potřeba takové okliky.
Editoval enumag (12. 5. 2014 23:33)
- enumag
- Člen | 2118
@Majkl578: Balík nette/routing je zatím testovací takže správné místo pro report je nette/application že?
- Zax
- Člen | 370
Bylo by taky fajn, kdyby router uměl nativně překládat názvy komponent tvořené multiplierem a „do“ parametry.
Trochu jsem si svůj script ještě upravil, takže můžu tvořit třeba takovéto routy:
$router[] = new Routers\Route('admin/skupiny[/zobrazit-opravneni-<o>][/strana-<pg>][/skupina-<r>][/pravidla-skupiny-<p>[/strana-<pg2>][/pravidlo-<rr>]][/akce-<do>[/zobrazit-<sp>]]', array(
'presenter' => 'Web:Back:Users',
'action' => 'roles',
NULL => $this->createAliases(
array(
'pg' => 'rolesPanel-rolesList-paginator-page',
'p' => 'rolesPanel-rolesList-editPermissions',
'r' => 'rolesPanel-rolesList-id',
'o' => 'rolesPanel-rolesList-showPermissions',
'pg2' => 'rolesPanel-rolesList-permissions-<p>-paginator-page',
'rr' => 'rolesPanel-rolesList-permissions-<p>-id',
'sp' => 'rolesPanel-rolesList-show'
),
array(
'vytvorit-skupinu' => 'rolesPanel-rolesList-add',
'upravit-skupinu' => 'rolesPanel-rolesList-edit',
'odstranit-skupinu' => 'rolesPanel-rolesList-delete',
'vytvorit-pravidlo' => 'rolesPanel-rolesList-permissions-<p>-add',
'upravit-pravidlo' => 'rolesPanel-rolesList-permissions-<p>-edit',
'odstranit-pravidlo' => 'rolesPanel-rolesList-permissions-<p>-delete',
'prepnout-opravneni' => 'rolesPanel-rolesList-toggleShowPermissions',
'prepnout-pravidla' => 'rolesPanel-rolesList-editPermissions'
)
)));
První pole jsou aliasy pro parametry, druhé pole jsou aliasy pro „do“ a všimněte si, že se odkazuji na parametr <p>, který obsahuje IDčko, které se používá v multiplieru. Výsledná URL pak vypadá třeba takto:
admin/skupiny/strana-3/pravidla-skupiny-30/strana-2/pravidlo-50/akce-upravit-pravidlo
místo zběsilosti typu
rolesPanel-rolesList-paginator-page=3&rolesPanel-rolesList-editPermissions=30&rolesPanel-rolesList-permissions-30-paginator-page=2&rolesPanel-rolesList-permissions-30-id=50&do=rolesPanel-rolesList-permissions-30-edit
Quick n dirty solution (určitě to jde napsat líp..)
protected function findTokens($name) {
return Nette\Utils\Strings::match($name, '~(\<[a-z-]\>)+~i');
}
protected function createFullName($tokens, $params, $aliases, $fullName) {
foreach($tokens as $token) {
$token2 = substr($token, 1, -1);
if(isset($params[$token2])) {
$fullName = str_replace($token, $params[$token2], $fullName);
} else if(isset($aliases[$token2]) && isset($params[$aliases[$token2]])) {
$fullName = str_replace($token, $params[$aliases[$token2]], $fullName);
}
}
return $fullName;
}
protected function createAliases($aliases, $doAliases = array()) {
$that = $this;
return array(
Routers\Route::FILTER_IN => function($params) use ($aliases, $doAliases, $that) {
if(isset($params['do'])) {
foreach($doAliases as $doAlias => $doFullName) {
$doTokens = $that->findTokens($doFullName);
if($doTokens) {
$doFullName = $that->createFullName($doTokens, $params, $aliases, $doFullName);
}
if($params['do'] == $doAlias)
$params['do'] = $doFullName;
}
}
foreach($aliases as $alias => $fullName) {
if(isset($params[$alias])) {
$tokens = $that->findTokens($fullName);
if($tokens) {
$fullName = $that->createFullName($tokens, $params, $aliases, $fullName);
}
$params[$fullName] = $params[$alias];
unset($params[$alias]);
}
}
return $params;
},
Routers\Route::FILTER_OUT => function($params) use ($aliases, $doAliases, $that) {
if(isset($params['do'])) {
foreach($doAliases as $doAlias => $doFullName) {
$doTokens = $that->findTokens($doFullName);
if($doTokens) {
$doFullName = $that->createFullName($doTokens, $params, $aliases, $doFullName);
}
if($params['do'] == $doFullName)
$params['do'] = $doAlias;
}
}
foreach($aliases as $alias => $fullName) {
$tokens = $that->findTokens($fullName);
if($tokens) {
$fullName = $that->createFullName($tokens, $params, $aliases, $fullName);
}
if(isset($params[$fullName])) {
$params[$alias] = $params[$fullName];
unset($params[$fullName]);
}
}
return $params;
}
);
}
Editoval Zax (13. 5. 2014 18:19)