【问题标题】:Multiple Slim routes with the same signature具有相同签名的多条 Slim 路由
【发布时间】:2016-01-20 10:25:40
【问题描述】:

我们正在考虑使用 Slim 3 作为我们 API 的框架。我搜索了 SO 和 Slim 文档,但找不到问题的答案。如果我们有不同的路由文件(例如 v1、v2 等)并且如果两个路由具有相同的签名,则会引发错误。有没有办法级联路由,以便使用特定签名的最后加载路由?

比如v1.php有GET ("/test")的路由,v2.php也有这个路由,可以用最新版本吗?更简单的是,如果一个路由文件包含两个具有相同签名的路由,有没有办法使用后一种方法(并且不会引发错误)?

here 提出了类似的问题,但这使用了钩子(根据here,已从 Slim 3 中删除)

【问题讨论】:

  • 这个有什么用,为什么会有重复的路由呢?
  • API 可以有不同版本的签名。这是将它们全部加载,然后只制作“实时”最新版本。本质上,具有相同签名的两条路由会导致错误。
  • 为什么不只包括最新版本?
  • 还有许多自定义位置(可能会从早期文件中加载一些定义,但不是全部)

标签: slim slim-3


【解决方案1】:

我查看了 Slim 代码,但没有找到允许重复路由(防止异常)的简单方法。 新的 Slim 使用 FastRoute 作为依赖。它调用FastRoute\simpleDispatcher 并且不提供任何配置可能性。即使它确实允许某些配置,FastRoute 也没有任何允许重复路由的内置选项。需要 DataGenerator 的自定义实现。

但是按照上面的说明,我们可以通过向 Slim App 传递一个自定义的Router 来获得一个自定义的DataGenerator,该Router 会实例化一些FastRoute::Dispatcher implementation,然后使用自定义的DataGenerator

首先是CustomDataGenerator(让我们从\FastRoute\RegexBasedAbstract\FastRoute\GroupCountBased 复制和粘贴一些简单的方法)

class CustomDataGenerator implements \FastRoute\DataGenerator {
    /*
     * 1. Copy over everything from the RegexBasedAbstract
     * 2. Replace abstract methods with implementations from GroupCountBased
     * 3. change the addStaticRoute and addVariableRoute
     * to the following implementations
     */
    private function addStaticRoute($httpMethod, $routeData, $handler) {
        $routeStr = $routeData[0];

        if (isset($this->methodToRegexToRoutesMap[$httpMethod])) {
            foreach ($this->methodToRegexToRoutesMap[$httpMethod] as $route) {
                if ($route->matches($routeStr)) {
                    throw new BadRouteException(sprintf(
                        'Static route "%s" is shadowed by previously defined variable route "%s" for method "%s"',
                        $routeStr, $route->regex, $httpMethod
                    ));
                }
            }
        }
        if (isset($this->staticRoutes[$httpMethod][$routeStr])) {
            unset($this->staticRoutes[$httpMethod][$routeStr]);
        }
        $this->staticRoutes[$httpMethod][$routeStr] = $handler;
    }
    private function addVariableRoute($httpMethod, $routeData, $handler) {
        list($regex, $variables) = $this->buildRegexForRoute($routeData);
        if (isset($this->methodToRegexToRoutesMap[$httpMethod][$regex])) {
            unset($this->methodToRegexToRoutesMap[$httpMethod][$regex]);
        }
        $this->methodToRegexToRoutesMap[$httpMethod][$regex] = new \FastRoute\Route(
            $httpMethod, $handler, $regex, $variables
        );
    }
}

然后自定义Router

class CustomRouter extends \Slim\Router {
    protected function createDispatcher() {
        return $this->dispatcher ?: \FastRoute\simpleDispatcher(function (\FastRoute\RouteCollector $r) {
            foreach ($this->getRoutes() as $route) {
                $r->addRoute($route->getMethods(), $route->getPattern(), $route->getIdentifier());
            }
        }, [
            'routeParser' => $this->routeParser,
            'dataGenerator' => new CustomDataGenerator()
        ]);
    }
}

最后用自定义路由器实例化 Slim 应用

$app = new \Slim\App(array(
    'router' => new CustomRouter()
));

上面的代码,如果检测到重复的路由,则删除之前的路由并存储新的路由。

我希望我没有错过任何更简单的方法来实现这个结果。

【讨论】:

    猜你喜欢
    • 2012-07-16
    • 1970-01-01
    • 2021-08-23
    • 2021-08-05
    • 1970-01-01
    • 2018-01-08
    • 1970-01-01
    • 2020-12-30
    • 1970-01-01
    相关资源
    最近更新 更多