Jedna routa pro více stejných komponent na různých místech
- joe
- Člen | 313
Ahoj, takový trochu obecný dotaz. Pokud mám v sobě poskládané komponenty, například
- UserList
- Paginator
a komponentu v šabloně vypisuju {control userList}
, pak se
generuje adresa stránkování například
/userList-paginator-page=2
V routě to pak můžu zachytit maskou
<userList-paginator-page>
a změnit si URL jak chci.
Nevím jak ale řešit situaci, kdy mám takových komponent třeba 30,
OrderList
, AdminList
, FunctionList
,
… apod.
Je nějaká jednoduchá možnost, jak mít hezké URL adresy, aniž bych
tvořil 30 rout? Řešením se může zdát vytvořit
komponenty stejného názvu {control list}
a pak měl masku jen
<list-paginator-page>
, tomu se ale chci vyhnout, protože pak
jednoduše po šablonách nedohledám, která komponenta je která… a 30 rout
kvůli stránkování vytvářet nechci (zanořených komponent může být
více, takže pro 2 bych tvořil rout už 60).
(Otázkou je, jestli je dobrý mít Paginator v komponentě, jen jsem si to chtěl z presenterů trochu uklidit)
Jak to řešíte? Díky!
- Petr Steinbauer
- Člen | 26
Ahoj,
nehledáte náhodou „Volitelné sekvence v routě“ – dokumentace: https://doc.nette.org/…tion/routing#…
tedy něco jako:
$router->addRoute(
'[<lang [a-z]{2}>[-<sublang>]/]<name>[/page-<page=0>][/user-<user=0>][/exklusivity-<exklusivity=0>]',
'Homepage:default'
);
Podstatné je, že při generování výsledné URL se usiluje o nejkratší variantu, takže všechno, co lze vynechat, se vynechá.
čili adresy budete mít krásné, stačí jen použít ty prefixy
(page-7
například) – a vše máte „v jedné routě“
- Petr Steinbauer
- Člen | 26
joe napsal(a):
To není ono :) Já bych spíš potřeboval regulární výrazy přímo v masce, něco na způsob
<(user|order|admin|car|...)List-paginator-page>
.
Omlouvám se, ale z napsaného není poznat co myslíte
Pokud to myslíte tak, aby Vám to user|order|admin|car
mělo
volat jednotlivé jednotlivé presentery (ukázka), nebo akce, tak to
pochopitelně jde…
`[<presenter=Homepage>/[<action=default>]]
`
když to rozšíříte o ty další volitelné sekvence, bude routa skutečně dynamická – zavolá Vám vámi vybraný presenter, akci a vybrané parametry udělá na hezkou url…
https://doc.nette.org/…tion/routing#…
Ale jak říkám, asi jsem přesně nepochopil co jste tím „regulární výrazy přímo v masce“ myslel.
- joe
- Člen | 313
Zkusím to vysvětlit jinak na příkladu:
Mám komponenty UserList
, CarList
,
FunctionList
, ProductList
, … a ty do šablon
vkládám pomocí {control userList}
,
{control carList}
, {control functionList}
,
{control productList}
, …
Každá taková komponenta náleží hlavnímu presenteru, tedy
UserPresenter
, CarPresenter
,
FunctionPresenter
, ProductPresenter
, … a uvnitř
každé komponenty, resp. v předkovi AbstractList
je
stránkování, komponenta Paginator
.
Pokud neberu v potaz žádnou routu, odkazy na druhou stránku vypadají následovně:
- /user?userList-paginator-page=2
- /car?carList-paginator-page=2
- /function?functionList-paginator-page=2
atd.
Já bych rád měl odkazy ve tvaru
- /user/2
- /car/2
- /function/2
…
V routách mohu zachytit jenom (pravděpodobně jenom) parametry, které
dopředu znám, tzn. že masky by byly
<userList-paginator-page>
,
<carList-paginator-page>
,
<functionList-paginator-page>
, … a to znamená, že pro
každou takovou masku bych vytvářel jednu routu. A pokud bych přidal další
takový seznam se stránkováním, musel bych přidávat další routu a tomu se
chci vyhnout, proto hledám nějaké elegantní řešení, pokud
existuje :-)
- Petr Steinbauer
- Člen | 26
joe napsal(a):
V routách mohu zachytit jenom (pravděpodobně jenom) parametry, které dopředu znám, tzn. že masky by byly
<userList-paginator-page>
,<carList-paginator-page>
,<functionList-paginator-page>
, … a to znamená, že pro každou takovou masku bych vytvářel jednu routu. A pokud bych přidal další takový seznam se stránkováním, musel bych přidávat další routu a tomu se chci vyhnout, proto hledám nějaké elegantní řešení, pokud existuje :-)
Aha, díky…
pokud neexistuje důvod proč by měla každá komponenta mít vlastní
unikátní get parametr userList-paginator-page
vs.
carList-paginator-page
tak bych zavedl jednotný parametr
(například page
) a pak skutečně nemusíte zavádět více
rout – stačí jen jedna routa s volitelným jedním page parametrem.
Pokud ten důvod na unikátnost je – a chcete hezké url adresy – domnívám se, že ten seznam rout budete muset napsat.
- joe
- Člen | 313
Parametr ($page
je persistentní) vytváří Nette automaticky
podle názvu komponent a jejich zanoření. Mohl bych to mít tak, že všechny
takové seznamy budu vytvářet přes createComponentList
a pak
místo {control carList}
psát jen {control list}
,
jenže jednoduše ze šablony nerozeznám, o jakou komponentu jde a tomu se
chci vyhnout. Rád bych se pak dopracoval v IDE k tomu, že podržím CTRL a
kliknu na {control carList}
a hodí mě to do šablony
carList.latte
.
Editoval joe (17. 8. 2020 23:27)
- Petr Steinbauer
- Člen | 26
Rozumím,
v tom případě já neznám řešení a pokud tady není nikdo chytřejší,
tak si budeš muset ty routy vytvořit :)
- David Matějka
- Moderator | 6445
Ahoj, asi by šel použít globální filtr, kde můžeš provést jakoukoliv transformaci parametrů. Máš na vstupu název presenteru i ten parametr page, tak dle presenteru (buď přes nějakou mapu nebo pokud je to jednoznačně mapovatelný dle pravidel, tak nějakou logikou) přemapuješ parametr page na jiný parametr.
- joe
- Člen | 313
@DavidMatějka mi poslal přímo kód, který jsem přesně potřeboval. Už nevím teda jak jsem to zkoušel dřív, že mi to nefungovalo :-D Zase jsem o trochu blíž myšlence routování.
$router[] = new Route('<presenter>[/<action>][/<page>]', [
null => [
Route::FILTER_IN => function (array $params) {
if ($params['presenter'] === 'User') { // tady si určit logiku, na kterém presenteru komponenta je
$params['userList-paginator-page'] = $params['page'];
unset($params['page']);
}
return $params;
},
Route::FILTER_OUT => function (array $params) {
if (isset($params['userList-paginator-page'])) {
$params['page'] = $params['userList-paginator-page'];
unset($params['userList-paginator-page']);
}
},
]
]);
- Petr Steinbauer
- Člen | 26
joe napsal(a):
@DavidMatějka mi poslal přímo kód, který jsem přesně potřeboval. Už nevím teda jak jsem to zkoušel dřív, že mi to nefungovalo :-D Zase jsem o trochu blíž myšlence routování.
$router[] = new Route('<presenter>[/<action>][/<page>]', [ null => [ Route::FILTER_IN => function (array $params) { if ($params['presenter'] === 'User') { // tady si určit logiku, na kterém presenteru komponenta je $params['userList-paginator-page'] = $params['page']; unset($params['page']); } return $params; }, Route::FILTER_OUT => function (array $params) { if (isset($params['userList-paginator-page'])) { $params['page'] = $params['userList-paginator-page']; unset($params['userList-paginator-page']); } }, ] ]);
Aha, tím si lze „podvrhnout“ opravdu cokoliv – pěkný