【问题标题】:How to implement a default routing behaviour with Lumen or Slim framework如何使用 Lumen 或 Slim 框架实现默认路由行为
【发布时间】:2016-04-26 02:34:38
【问题描述】:

我正在考虑在一个项目中使用 Lumen 或 Slim,并想知道是否可以根据目录结构自动加载控制器,而不必注册所有路由。

这就是我希望自动加载工作的方式。

示例目录/类结构:

 /app/Http/Controllers/
    Foo/
        BarController.php        # App\Http\Controllers\Foo\BarController

如果路线是

example.com/foo/bar == App\Http\Controllers\Foo\BarController::index()

example.com/foo/bar/add == App\Http\Controllers\Foo\BarController::add()

注册的路由应该优先于自动加载的类。

我找到了一种基于 Opencart 的路由方法的方法。 他们有超过 396 个控制器的 1145 种不同的公共方法,这些方法都被调用而没有明确说明控制器和方法。 这是我的尝试。

.htaccess

RewriteRule ^([^?]*) index.php?route=$1 [L,QSA]

app/Http/routes.php

$route = array_shift($_GET);
$method_name = '';

$parts = explode('/', preg_replace('/[^a-zA-Z0-9_\/]/', '', (string)$route));

while ($parts) {

    $class = '\App\Http\Controllers\\' . implode('\\', $parts);

    if (class_exists($class)){
        $app->match($route, $class . '@' . method_exists($class, $method_name) ? $method_name : 'index');
        break;
    } else {
        $method_name = array_pop($parts);
    }
}

如果需要的路由不同于 Opencart 的默认路由,则使用 .htaccess RewriteRuleresponse->redirect 路由到备用控制器。

我会使用他们的方法,但在 app/Http/routes.php。像这样

// route overrides 
$app->get('/', 'common/home@index');
$app->get('/home', 'common/home@index');

我是否认为这会使应用程序运行得更快,因为它不必搜索所有已注册的路线以进行匹配?

有没有更好的方法来执行这个自动路由过程?

【问题讨论】:

  • 您正在尝试做的事情不会让您的应用程序运行得更快或更慢,出于某种原因,人们为了优化而专注于错误的事情。但是,您的想法完全违背了路由的目的。你想要定义一个路由并且你想要明确说明要处理它的内容。如果您正在尝试“自动化”路由处理程序,那么您正在实施隐藏的魔法。最终,路由将与处理程序(控制器/函数)匹配。明确说明处理它的方法要好得多。除了麻烦之外,您从这种类型的自动化中一无所获。

标签: php url-routing slim lumen psr-4


【解决方案1】:

我认为您可以结合使用 reflection 和 Slim 3 对 defining routes with controller methods instead of closures 的支持来完成这项工作。

基本策略如下:

  1. 搜索每个控制器类(使用glob 或自动加载器);
  2. 对于每个类,调用ReflectionClass::getMethods,使用ReflectionMethod::IS_PUBLIC 过滤器,这样您就只能获取该类的公共方法;
  3. 使用ReflectionClass::getName 获取类名,使用ReflectionClass::getNamespaceName 获取命名空间(如有必要);
  4. 根据命名空间、类名和方法名构建您的路由签名,可能使用像 https://github.com/cocur/slugify 这样的 slugification 库;
  5. 生成对应路由$app->get($route_signature, "$class_name:$method_name")

这是一个有趣的想法,尽管您需要非常小心,以免意外暴露您不希望客户端直接访问的任何方法。其他一些注意事项:

  • 反射非常慢,因此您可能希望将其实现为更多的构建步骤,缓存生成的路由,而不是在每次请求时即时重新生成它们。
  • 您可能需要一些额外的命名约定来区分 HTTP 动词。例如,所有与GET 路由对应的方法名称都以get 开头。所以你可能有\Foo\BarController::getAdd\Foo\BarController::postAdd等。
  • 构造参数化路由 (/bar/add/{id}) 将需要更多工作,因为您可能希望使用 ReflectionFunctionAbstract::getParameters 提取相应的方法参数。同样,您需要就如何根据这些参数构建路线制定一些约定。

【讨论】:

    猜你喜欢
    • 2014-08-27
    • 2016-10-14
    • 1970-01-01
    • 2015-12-10
    • 1970-01-01
    • 2017-10-13
    • 1970-01-01
    • 1970-01-01
    • 2018-01-05
    相关资源
    最近更新 更多