You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Nette Router实现数据库页面映射至域名根并兼容现有路由

Nette Router 配置:优先匹配数据库页面路径

问题背景

当前路由形式:

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

期望路由形式:

/post1-url
/post2-url/slashed

需要让Nette Router优先匹配数据库中的路径字符串,匹配失败后再走现有路由规则,现有路由代码如下:

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;
}

已有处理数据库文章的Presenter动作,需将数据库匹配逻辑与RouteList结合。

解决方案

核心思路

Nette Router按路由添加顺序匹配,优先级从上到下。只需在路由链最前端加入数据库匹配逻辑即可实现优先匹配。

方法1:回调路由(轻量推荐)

修改createRouter方法,在最前面添加回调路由实现数据库匹配:

public static function createRouter(): RouteList
{
    $router = new RouteList;

    // 1. 优先匹配数据库页面路径
    $router->addRoute('<path .+>', function (array $params): ?array {
        $requestedPath = $params['path'];
        // 替换为你的数据库查询逻辑:检查路径是否存在
        $page = YourPageModel::findOneBy(['url' => $requestedPath]);
        
        if ($page) {
            // 匹配成功,返回对应Presenter、Action及参数
            return [
                'presenter' => 'Home', // 替换为处理数据库页面的Presenter
                'action' => 'viewPage', // 替换为对应Action
                'slug' => $page->slug, // 传递页面标识给Action
            ];
        }
        
        // 匹配失败,返回null,交由后续路由处理
        return null;
    });

    // 2. 原有路由规则保持不变
    $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;
}

说明:

  • <path .+> 匹配任意非空路径,覆盖所有可能的数据库页面路径
  • 回调内完成数据库查询,匹配成功则返回路由参数,失败则放行给后续规则
  • 建议给数据库url字段加索引,提升查询效率

方法2:自定义Route类(复杂场景适用)

若需更复杂的匹配逻辑,可自定义Route类继承Nette\Routing\Route,重写match方法:

class DatabasePageRoute extends \Nette\Routing\Route
{
    public function match(\Nette\Http\IRequest $request): ?array
    {
        $path = ltrim($request->getUrl()->getPath(), '/');
        $page = YourPageModel::findOneBy(['url' => $path]);
        
        if ($page) {
            return [
                'presenter' => 'Home',
                'action' => 'viewPage',
                'slug' => $page->slug,
            ];
        }
        
        // 不匹配则返回null,交给后续路由
        return null;
    }
}

然后在createRouter中添加:

$router->addRoute(new DatabasePageRoute);
// 后续接原有路由规则

注意事项

  • 路由顺序:数据库匹配路由必须放在最前面,确保优先级最高
  • 性能优化:频繁数据库查询会影响性能,可通过Nette Cache组件或Redis缓存已存在的路径
  • 冲突处理:确保数据库路径不会与/auth、/admin等系统路由重复,或在查询时排除这些系统路径

内容的提问来源于stack exchange,提问作者PM_KLS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 04:16:28