具有相同签名的多个 Slim 路由
Multiple Slim routes with the same signature
我们正在考虑使用 Slim 3 作为我们 API 的框架。我已经搜索过 SO 和 Slim 文档,但找不到问题的答案。如果我们有不同的路由文件(例如 v1、v2 等)并且如果两个路由具有相同的签名,则会抛出错误。有什么方法可以级联路由,以便使用特定签名的最后加载路由?
比如v1.php有一个路由给GET ("/test")
,v2.php也有这个路由,能不能用最新的版本?更简单的是,如果一个路由文件包含两个具有相同签名的路由,是否有办法使用后一种方法(并且不会抛出错误)?
问了一个类似的问题here but this uses hooks (which have been removed from Slim 3 as per here)
我查看了 Slim 代码,但没有找到允许重复路由(防止异常)的简单方法。
新的 Slim 使用 FastRoute 作为依赖。它调用 FastRoute\simpleDispatcher
并且不提供任何配置可能性。即使它确实允许一些配置,FastRoute 也没有任何 built-in 选项来允许重复的路由。需要 DataGenerator
的自定义实现。
但是按照上面的说明,我们可以通过将自定义 Router
传递给 Slim App 来获得自定义 DataGenerator
实例化一些 FastRoute::Dispatcher implementation
然后使用自定义 DataGenerator
.
首先是 CustomDataGenerator
(让我们走简单的路,从 \FastRoute\RegexBasedAbstract and \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()
));
上面的代码,如果检测到重复的路线,则删除以前的路线并存储新路线。
我希望我没有错过实现此结果的任何更简单的方法。
我们正在考虑使用 Slim 3 作为我们 API 的框架。我已经搜索过 SO 和 Slim 文档,但找不到问题的答案。如果我们有不同的路由文件(例如 v1、v2 等)并且如果两个路由具有相同的签名,则会抛出错误。有什么方法可以级联路由,以便使用特定签名的最后加载路由?
比如v1.php有一个路由给GET ("/test")
,v2.php也有这个路由,能不能用最新的版本?更简单的是,如果一个路由文件包含两个具有相同签名的路由,是否有办法使用后一种方法(并且不会抛出错误)?
问了一个类似的问题here but this uses hooks (which have been removed from Slim 3 as per here)
我查看了 Slim 代码,但没有找到允许重复路由(防止异常)的简单方法。
新的 Slim 使用 FastRoute 作为依赖。它调用 FastRoute\simpleDispatcher
并且不提供任何配置可能性。即使它确实允许一些配置,FastRoute 也没有任何 built-in 选项来允许重复的路由。需要 DataGenerator
的自定义实现。
但是按照上面的说明,我们可以通过将自定义 Router
传递给 Slim App 来获得自定义 DataGenerator
实例化一些 FastRoute::Dispatcher implementation
然后使用自定义 DataGenerator
.
首先是 CustomDataGenerator
(让我们走简单的路,从 \FastRoute\RegexBasedAbstract and \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()
));
上面的代码,如果检测到重复的路线,则删除以前的路线并存储新路线。
我希望我没有错过实现此结果的任何更简单的方法。