Router – víceúrovňové skládání URL z databáze

cafesk8
Člen | 103
+
0
-

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)