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ý