Router – víceúrovňové skládání URL z databáze
- cafesk8
- Člen | 103
Zdravím,
mám v modulu Front presenter Category a tam action default – v databázi mám kategorie, které mají hierarchickou strukturu, kterou určuje sloupec parent_id.
Nyní mám router takto, který mi správně překládá adresy na např.:
- domena.cz/sport
- domena.cz/hokej
- domena.cz/elektro
- domena.cz/mobilni-telefony
public static function createRouter(CategoryRepository $categoryRepository): RouteList {
$router = new RouteList;
$router[] = $adminRouter = new RouteList('Admin');
$adminRouter[] = new Route('admin/<presenter>/<action>/[<id>]', 'Homepage:default');
$router[] = $frontRouter = new RouteList('Front');
$frontRouter[] = new Route('<id>', array(
'id' => array(
// get id by URL
Route::FILTER_IN => function ($url) use ($categoryRepository) {
$page = $categoryRepository->findOneBy(['slug' => $url]);
if(!$page) {
return null;
}
return $page->id;
},
// GET URL BY ID
Route::FILTER_OUT => function ($id) use ($categoryRepository) {
if(!is_numeric($id)){
return $id;
} else {
$page = $categoryRepository->find($id);
return $page->slug;
}
}
),
'presenter' => 'Category',
'action' => 'default'
));
$frontRouter[] = new Route('<presenter>/<action>[/<id>]', 'Homepage:default');
return $router;
}
Já bych však potřeboval router, který mi ty adresy přeloží rekurzivně dle „všech“ parent_id v databázi na např.:
- domena.cz/sport
- domena.cz/sport/hokej
- domena.cz/elektro
- domena.cz/elektro/mobilni-telefony
- domena.cz/elektro/mobilni-telefony/android
Předpokládám, že mám asi napsanou špatnu tu masku routy s tím <id>, ale to úplně nevím jak zapsat, když nevím kolik těch částí v URL bude.
Zkoušel jsem ve FILTER_IN a FILTER_OUT přidat funkce které by mi routu poskládaly, ale jakmile do ní zakomponuju lomítka, tak to přestane fungovat, jinými slovy:
- domena.cz/sporthokej – funguje
- domena.cz/sport/hokej – nefunguje (vrací základní např. domena.cz/category/default/66).
Také jsem zkoušel do DB při vytváření kategorií rovnou ukládat již složenou routu, tudíž ve sloupečku slug ukládám rovnou např. „sport/hokej“ namísto pouze „hokej“, ale výsledek byl stejný jako při skládání routy ve FILTER_IN/OUT.
Nevíte někdo jak na to? Zkoušel jsem tady hledat, ale nepodařilo se mi, přitom to je věc, kterou jistě musela řešit spoust z Vás.
Nebo myslíte si, že se na to mám vykašlat a stačily by URL ve tvaru: domena.cz/elektro-mobilni-telefony-android?
EDIT: SOLVED – změnil jsem v routě masku na
<id .*>/
a v Route::FILTER_OUT
vracím
celou cestu.
Celý kód:
$frontRouter[] = new Route('<id .*>/', array(
'id' => array(
// get id by URL
Route::FILTER_IN => function ($url) use ($categoryRepository) {
$slugs = explode('/', $url);
$lastSlug = end($slugs);
$page = $categoryRepository->findOneBy(['slug' => $lastSlug]);
if(!$page) {
return null;
}
return $page->id;
},
// GET URL BY ID
Route::FILTER_OUT => function ($id) use ($categoryRepository) {
if(!is_numeric($id)){
return $id;
} else {
$slug = $categoryRepository->getAllParentsForUrl($id); // vrací např. "elektro/mobilni-telefony/android"
return $slug;
}
}
),
'presenter' => 'Category',
'action' => 'default'
));
Editoval cafesk8 (15. 7. 2020 15:29)