Jedna routa na dva různé prezentery
- mkoula
- Backer | 57
Mám routu:
$router->addRoute('/[<lang en|de|it|fr>/]<id \d+>/<slug>', [
'presenter' => 'Accommodation',
'action' => 'default',
'lang' => 'en',
]);
Mám různá URL:
/107/hotel-denis
/308/hotel-hilton
/395/dream-yacht
/257/yacht-vpm-cocktail-creole
Potřeboval bych nějak udělat, aby pokud ve slugu existuje slovo
‚yacht‘ – vždy vše směřoval na YachtPresenter::default()
a cokoliv ostatního na AccommodationPresenter::defaut()
Hraju si už hodinu s různými filtry a prostě ne a ne. Varianta je si
udělat pro tuhle jednou routu vlastní router, ale pořád si říkám, že by
to snad nějak jít mohlo. Jednoduše to jde s návratovou funkcí, kam si
předám parameter, ale ta vrací už obsah.
Nenapadne někoho něco?
PS:
Jde to obějít v AccommodationPresenteru, ale pak Tracy neukáže správný Presenter a člověk nevidí kam to vede a musí chodit skrz kód. A já si říkám, že by to nějak jít mělo…
public function actionDefault(int $id, ?string $slug)
{
// Redirect to Yacht presenter if "yacht" is in the slug
if (str_contains($slug, 'yacht')) {
$this->forward('Yacht:default', ['id' => $id, 'slug' => $slug]);
}
....
}
Editoval mkoula (23. 9. 14:44)
- Kamil Valenta
- Člen | 820
$router->addRoute('/[<lang en|de|it|fr>/]<id \d+>/<slug>-yacht', [
'presenter' => 'Yacht',
'action' => 'default',
'lang' => 'en',
]);
$router->addRoute('/[<lang en|de|it|fr>/]<id \d+>/<slug>', [
'presenter' => 'Accommodation',
'action' => 'default',
'lang' => 'en',
]);
Třeba jen takto?
- mkoula
- Backer | 57
Tohle mi bohužel změní stávající URL, kterou se snažím zachovat…
Kamil Valenta napsal(a):
$router->addRoute('/[<lang en|de|it|fr>/]<id \d+>/<slug>-yacht', [ 'presenter' => 'Yacht', 'action' => 'default', 'lang' => 'en', ]); $router->addRoute('/[<lang en|de|it|fr>/]<id \d+>/<slug>', [ 'presenter' => 'Accommodation', 'action' => 'default', 'lang' => 'en', ]);
Třeba jen takto?
- MajklNajt
- Člen | 498
a niečo na tento spôsob? (píšem z hlavy, netestoval som)
$router->addRoute('/[<lang en|de|it|fr>/]<id \d+>/<slug>', [
'presenter' => 'Accommodation',
'action' => 'default',
null => [
Route::FilterIn => function (array $params): array {
if (str_contains($params['slug'], 'yacht')) {
$params['presenter'] = 'Yacht';
}
return $params;
},
Route::FilterOut => function (array $params): array {
if (str_contains($params['slug'], 'yacht')) {
$params['presenter'] = 'Yacht';
}
return $params;
},
],
]);
Editoval MajklNajt (23. 9. 14:56)
- mkoula
- Backer | 57
Tak mě to přesměruje na URL, které není v routingu, ale odpovídá
pravidlům routování:
/yacht/default/257?slug=yacht-vpm-cocktail-creole
Což také není co bych chtěl. V podstatě se zpracuje jen filter „out“. Ten změní presenter a snaží se to najít jinou routu pro Yacht, která nexistuje a vytvoří tohle…
MajklNajt napsal(a):
a niečo na tento spôsob? (píšem z hlavy, netestoval som)
$router->addRoute('/[<lang en|de|it|fr>/]<id \d+>/<slug>', [ 'presenter' => 'Accommodation', 'action' => 'default', null => [ Route::FilterIn => function (array $params): array { if (str_contains($params['slug'], 'yacht')) { $params['presenter'] = 'Yacht'; } return $params; }, Route::FilterOut => function (array $params): array { if (str_contains($params['slug'], 'yacht')) { $params['presenter'] = 'Yacht'; } return $params; }, ], ]);
Editoval mkoula (23. 9. 23:17)
- m.brecher
- Generous Backer | 871
@mkoula
je nutné mít na vybrané klienty samostatný presenter ?? Nevidím do detailu, jaks se zpracování VIP yacht klientů liší, ale šel bych na to spíš tak, že bych zpracování rozvětvil až v AccommodationPresenter::default().
Popiš rozdíly ve zpracování více do hloubky, třeba něco vymyslíme.
- Kamil Valenta
- Člen | 820
mkoula napsal(a):
Tak mě to přesměruje na URL, které není v routingu, ale odpovídá pravidlům routování:
/yacht/default/257?slug=yacht-vpm-cocktail-creole
Což také není co bych chtěl. V podstatě se zpracuje jen filter „out“. Ten změní presenter a snaží se to najít jinou routu pro Yacht, která nexistuje a vytvoří tohle…
Ukaž, jak v linku vytváříš odkazy a ukaž ideální celou kolekci rout.
- m.brecher
- Generous Backer | 871
@mkoula
Ještě mě napadlo v AccommodationPresenter::default() analyzovat $slug a pokud obsahuje ‘yacht’ provést redirect() na YachtPresenter::default(), pro který by se přidala routa třeba takhle:
$router->addRoute('/[<lang en|de|it|fr>/]/yacht/<id \d+>/<slug>', [
'presenter' => 'YachtPresenter',
'action' => 'default',
'lang' => 'en',
]);
- mkoula
- Backer | 57
To je podobné vyíz výše – cílem je neměnit stávající URL.
Ono stačí v Accommodation zavolat:
if (str_contains($slug, 'yacht')) {
$this->forward('Yacht:default', ['id' => $id, 'slug' => $slug]);
}
Pak to funguje i na stejné URL, jen Tracy tuto změnu nevidí a ukazuje,
že požadavek zpracovává AccommodationPresenter.
Asi chci moc :-)
Napsal jsem si vlastní AccommodationRouter jen pro tento příklad a v něm to funguje. Jen je to něco, co bych čekal, že půjde vyřešit ve standardním routování…
m.brecher napsal(a):
@mkoula
Ještě mě napadlo v AccommodationPresenter::default() analyzovat $slug a pokud obsahuje ‚yacht‘ provést redirect() na YachtPresenter::default(), pro který by se přidala routa třeba takhle:
$router->addRoute('/[<lang en|de|it|fr>/]/yacht/<id \d+>/<slug>', [ 'presenter' => 'YachtPresenter', 'action' => 'default', 'lang' => 'en', ]);
- Marek Bartoš
- Nette Blogger | 1274
Router zpracovává routy od první k poslední, při zpracování aktuální url i při jejím generování. Filtry jsou pouze mapování, spuštěné potom, co routu matchneš. Bez custom routy, která by se někam dotazovala zda ten záznam má, máš v routeru jen jednu možnost a to udělat adresu těch rout tak, aby nebyly zaměnitelné. To v tomhle případě lze tak, že si pro parametr <slug> definuješ regex, který vyžaduje, aby například slug končil na -yacht. A druhá routa by ideálně měla dělat přesný opak, aby i generování odkazu muselo jít přes ten správný presenter a slug -yacht ti neprošel i přes odkaz na accommodation presenter.
„Tracy tuto změnu nevidí a ukazuje, že požadavek zpracovává AccommodationPresenter“ – sounds like feature request
Editoval Marek Bartoš (24. 9. 20:50)
- Kamil Valenta
- Člen | 820
Marek Bartoš napsal(a):
Filtry jsou pouze mapování, spuštěné potom, co routu matchneš.
Toto může působit nepřesným dojmem, že filtry neovlivní, zda se routa matchne. Takže jen doplnění, že filtry to ovlivnit mohou.
mkoula napsal(a):
cílem je neměnit stávající URL
Stále nám, neznámo proč, tajíš podobu {plink} nebo n:href a aktuální podobu celého routeru. To se pak těžko hledá způsob, který by ti nezměnil URL…
- mkoula
- Backer | 57
Thaaank youuu :-D
To je přesně ono a nějak mě to úplně nenapadlo, protože se snažím složitějším regulárům v routingu vyhýbat, ale když bude jeden, asi ok
$router->addRoute('/[<lang en|de|fr|it>/]<id \d+>[/<slug [^/]*yacht[^/]*>]', [
'presenter' => 'Yacht',
'action' => 'default',
'lang' => $this->init->getDefaultLanguage(),
]);
$router->addRoute('/[<lang en|de|fr|it>/]<id \d+>[/<slug>]', [
'presenter' => 'Accommodation',
'action' => 'default',
'lang' => $this->init->getDefaultLanguage(),
])
Regulár to pořeší a vše funguje. Napsal jsem si vlastní router, což fungovalo stejně, jen je to věc extra. Ke všemu používám komponenty a je třeba napsat router, aby podporoval generování query stringů, kteřé řeší signály v komponentách.
Řešení v klasickém Nette routingu je jednodušší na správu a závislosti…
Marek Bartoš napsal(a):
Router zpracovává routy od první k poslední, při zpracování aktuální url i při jejím generování. Filtry jsou pouze mapování, spuštěné potom, co routu matchneš. Bez custom routy, která by se někam dotazovala zda ten záznam má, máš v routeru jen jednu možnost a to udělat adresu těch rout tak, aby nebyly zaměnitelné. To v tomhle případě lze tak, že si pro parametr <slug> definuješ regex, který vyžaduje, aby například slug končil na -yacht. A druhá routa by ideálně měla dělat přesný opak, aby i generování odkazu muselo jít přes ten správný presenter a slug -yacht ti neprošel i přes odkaz na accommodation presenter.
„Tracy tuto změnu nevidí a ukazuje, že požadavek zpracovává AccommodationPresenter“ – sounds like feature request
Jinak @DavidGrudl → ono zachycení volání
$this->forward()
v Presenteru někde v TracyBaru by asi
opravdu stálo za nějaký feature request o:)
Editoval mkoula (25. 9. 10:54)