Jedna routa pro více stejných komponent na různých místech

joe
Člen | 313
+
0
-

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
+
0
-

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ě“

joe
Člen | 313
+
0
-

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>.

Možná by to šlo nějak nasimulovat přes globální filtry, ale metodou pokus-omyl se mi to nepodařilo.

Editoval joe (17. 8. 2020 22:19)

Petr Steinbauer
Člen | 26
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
+1
-

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
+
+1
-

@DavidMatějka

Díky za potvrzení, že by to mohlo jít :) Zkusím si s tím ještě trochu pohrát, jak budu mít chvíli času a případně se tu poptám / ukážu, jak se mi to (ne)povedlo vyřešit.

Editoval joe (18. 8. 2020 11:45)

joe
Člen | 313
+
+1
-

@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
+
0
-

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ý