Search code examples
nette

nette router: match and RouteList


I'm trying to map pages from database to root of domain:

now I have have

/posts/post1-url
/posts/post2-url/slashed

I want

/post1-url
/post2-url/slashed

How can I make router that matches the strings above with db, and if not matched, continues matching routeList like below?

<?php
public static function createRouter(): RouteList
    {
        $router = new RouteList;
        $router->addRoute('/', 'Home:default');
        $router->addRoute('/auth', 'Auth:default');
        $router->addRoute('/auth/<action>', 'Auth:<action>');
        $router->addRoute('/admin', 'Admin:default');
        $router->addRoute('/admin[/<action>][/<slug>]', 'Admin:<action>');
        $router->addRoute('/<slug>', 'Home:viewPage');
        $router->addRoute('<presenter>/<action>', '<presenter>:<action>');
        return $router;
    }

I have presenter action that can process showing the database post, but found no way to match route list in action, or other way to combine the match+routeList


Solution

  • I am using this approach.

    BlogRouter.php

    <?php declare(strict_types=1);
    
    namespace App\Router;
    
    use Nette\Http\IRequest;
    use Nette\Http\UrlScript;
    use Nette\Routing\Router;
    use Nette\Utils\Strings;
    
    final class BlogRouter implements Router
    {
        private const Posts = [
            'first-page',
            'second/page',
        ];
    
        public function match(IRequest $httpRequest): ?array
        {
            $slug = Strings::trim($httpRequest->getUrl()->getPath(), '/');
    
            if (in_array($slug, self::Posts)) {
                return [
                    'presenter' => 'Blog',
                    'action' => 'post',
                    'slug' => $slug,
                ];
            }
    
            return null;
        }
    
        public function constructUrl(array $params, UrlScript $refUrl): ?string
        {
            if (!array_key_exists('slug', $params) || !in_array($params['slug'], self::Posts)) {
                return null;
            }
    
            return $refUrl->getHostUrl() . '/' . $params['slug'] . '/';
        }
    }
    

    RouterFactory.php

    <?php declare(strict_types=1);
    
    namespace App\Router;
    
    use Nette\Application\Routers\RouteList;
    use Nette\Routing\Router;
    use Nette\StaticClass;
    
    final class RouterFactory
    {
        use StaticClass;
    
        public static function createRouter(): RouteList
        {
            $router = new RouteList;
    
            $router->add(new BlogRouter());
            $router->addRoute('/<slug [0-9a-z-]+>/', 'Page:default');
            $router->addRoute('/', 'Homepage:default');
    
            return $router;
        }
    }
    

    You can simply update BlogRouter code to use database. But you should cache uris, not query them on each request.