Prefix cesty – chyba dokumentace + chyba v routě

m.brecher
Generous Backer | 873
+
0
-

Ahoj,

mám dvě poznámky

1. router prefix cesty – dokumentace

cca před rokem a půl jsem zkoušel routu s prefixem cesty tak jak to je v dokumentaci – tj. s lomítkem na začátku prefixu (jestli si dobře pamatuji) a fungovalo to:

https://doc.nette.org/…tion/routing#…

ukázka z dokumentace:

$router->withPath('/eshop')
	->addRoute('rss', 'Feed:rss')

Ale když jsem to nyní (nette/routing v3.0.3) testoval, tak ta verze s lomítkem na začátku prefixu nefunguje, zatímco verze bez lomítka funguje:

$router->withPath('/admin')
    ->addRoute('<presenter>/<action>[/<id>]', 'Entry:default');  //   /admin/   No route for HTTP request

$router->withPath('admin')
    ->addRoute('<presenter>/<action>[/<id>]', 'Entry:default');  //   /admin/   200 OK, Entry:default

Zřejmě došlo k opravě lomítka v prefixu cesty, protože lomítko by na začátku být opravdu nemělo, ale v dokumentaci to zůstalo postaru?

2. chyba v routě

Tato samotná routa funguje:

$router->addRoute('[<slug>]', 'Front:default');   //  /abc   Front:default, slug = 'abc'

Ale v kombinaci s druhou routou s prefixem cesty už nefunguje jak by měla:

$router->withPath('admin')
    ->addRoute('<presenter>/<action>[/<id>]', 'Entry:default');    #?
$router->addRoute('[<slug>]', 'Front:default');   //  /abc   přesměruje na /admin/front/?slug=abc

Stejně dopadne i jednodušší zápis s prefixem cesty:

$router->addRoute('admin/<presenter>/<action>[/<id>]', 'Entry:default');    #?
$router->addRoute('[<slug>]', 'Front:default');   //  /abc   přesměruje na /admin/front/?slug=abc

Tato jednoduchá kolekce dvou rout by měla fungovat tak, že všechny routy s prefixem /admin/ zachytí první routa a všechny ostatní druhá routa.

Vypadá to tak, že možná došlo v poslední verzi Nette k žádoucí opravě prefixu cesty tak, aby byl v souladu s ostatnímu pravidly – tedy bez lomítka na začátku, ale přitom došlo ke změně funkce.

V podstatě chci úplně jednoduchý systém url pro malinký webík, kde administrace není v samostatném modulu -je to pár presenterů a presentery administrace jsou přístupné přes prefix v url /admin. Veřejná část webu má jeden presenter Front s jednou akcí default a přijímá jeden parametr slug.

Prosím pokročilé znalce routování o vyjádření zda se mýlím a nevidím nějakou vlastní chybu, nebo je opravdu nějaká chyba v routeru.

Díky

Editoval m.brecher (11. 1. 2023 14:28)

m.brecher
Generous Backer | 873
+
0
-

Ahoj,

zkoušel jsem ještě downgradovat na nette/routing v.3.0.2, chová se to úplně stejně, na nette/routing v.3.0.1 už to nešlo, protože bych musel downgradovat i nette/application a to jsem už raději nedělal.

David Grudl
Nette Core | 8229
+
0
-

Samozřejmě v dokumentaci může být překlep, pošli prosím opravu s odstraněním toho lomítka. Na konci každé stránky je k tomu návod.

Proč to přesměrovává je vysvětlené tady https://doc.nette.org/…tion/routing#….

m.brecher
Generous Backer | 873
+
0
-

@DavidGrudl

dokumentace

pošli prosím opravu s odstraněním toho lomítka

OK pošlu

údajná chyba přesměrování

Proč to přesměrovává je vysvětlené tady

No seděl jsem nad tím další půlhodinu a nakonec jsem došel k závěru, že tam opravdu chyba není, i když to vypadalo že je. Router sice použije tu routu, kde první najde shodu a routy za ní ignoruje, ALE někdy i routa která následuje za routou která se použije ovlivňuje chování a tohle dělá problémy odhadnout.

Postupoval jsem takto

$router->addRoute('admin/<presenter>/<action>[/<id>]', 'Entry:default');

/admin přesměruje na /admin/
/admin/ mapuje na Entry:default

/admyn/ nesouhlasí prefix ⇒ No route for HTTP request
/ žádný prefix ⇒ No route for HTTP request

Chování je logické – pokud je prefix jiný, nebo žádný, router tuto routu ZAHODÍ

To se změní, když přidáme další routu:

$router->addRoute('admin/<presenter>/<action>[/<id>]', 'Entry:default');
$router->addRoute('', 'Front:content');

Routu pro Front:content dávám za routu s prefixem, protože jsem si v předchozím kroku otestoval, že první routa url bez prefixu zahodí.

Ne, nefunguje to tak, jak bychom očekávali:

/admin/ mapuje na Entry:default
/ přesměruje na /admin/front/content

Takže takhle to na první pohled vypadá, že specifičtější routa:

$router->addRoute('', 'Front:content');

je „přepsaná“ obecnější routou:

$router->addRoute('admin/<presenter>/<action>[/<id>]', 'Entry:default');

Router vyhodnotí obecnější routu jako kanonickou a přesměruje na ni. No nemá cenu s tím polemizovat, tak to je a je potřeba se s tím smířit. Navíc v dokumentaci je doporučeno řadit routy za sebou nejprve specifické, potom obecné – to jsme zde udělali obráceně a tak máme problém s přesměrováním.

Zkusme experimentovat, prohoďme pořadí rout – podle dokumentace nejprve specifickou, pak obecnou:

$router->addRoute('', 'Front:content');
$router->addRoute('admin/<presenter>/<action>[/<id>]', 'Entry:default');

/ mapuje na Front:content
/admin přesměruje na /admin/
/admin/ mapuje na Entry:default

Juch !! Funguje to jak potřebujeme – router mapuje Front:content na / a ostatní presentery na prefix /admin/.

Pro vícestránkový web bude potřeba předat do Front:content parametr slug:

$router->addRoute('[<slug>]', 'Front:content');
$router->addRoute('admin/<presenter>/<action>[/<id>]', 'Entry:default');

/ mapuje na Front:content, slug = null
/admin/ přesměruje na /admin
/admin mapuje na Front:content, slug = admin

Ano, toho jsme se obávali a proto jsme nejprve zkoušeli dát routu pro Front:content nakonec. Co s tím? Zkusme vyloučit hodnotu ‚admin‘ parametru slug:

$router->addRoute('[<slug (?!admin).*>]', 'Front:content');
$router->addRoute('admin/<presenter>/<action>[/<id>]', 'Entry:default');

/ mapuje na Front:content, slug = null
/admin přesměruje na /admin/
/admin/ mapuje na Entry:default

Hmmm… tak jednoduchý, že to jednodušší být nemůže a dělá to přesně to, co potřebuju. Ale strávil jsem na tom HODINU :)

Editoval m.brecher (11. 1. 2023 23:47)

David Grudl
Nette Core | 8229
+
0
-

Ale strávil jsem na tom HODINU :)

To není nic neobvyklého, tím si prošel opravdu každý :)

Víc jsem rozepsal v dokumentaci to pořadí rout, snad je to srozumitelné https://doc.nette.org/…tion/routing#…