2

我正在考虑将 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]

应用程序/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 RewriteRule或 aresponse->redirect路由到备用控制器。

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

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

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

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

4

1 回答 1

1

我认为你可以结合反射和 Slim 3 对使用控制器方法而不是闭包定义路由的支持来完成这项工作。

基本策略如下:

  1. 搜索每个控制器类(使用glob或自动加载器);
  2. 对于每个类,调用ReflectionClass::getMethods,使用ReflectionMethod::IS_PUBLIC过滤器,这样您就只能获取该类的公共方法;
  3. 获取类名 usingReflectionClass::getName和命名空间(如果需要) using 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. 同样,您需要就如何根据这些参数构建路线做出一些约定。
于 2016-04-05T18:18:17.063 回答