Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何使用Lumen或Slim框架实现默认路由行为_Php_Url Routing_Slim_Lumen_Psr 4 - Fatal编程技术网

Php 如何使用Lumen或Slim框架实现默认路由行为

Php 如何使用Lumen或Slim框架实现默认路由行为,php,url-routing,slim,lumen,psr-4,Php,Url Routing,Slim,Lumen,Psr 4,我正在考虑在一个项目中使用Lumen或Slim,想知道是否有可能基于目录结构自动加载控制器,而不必注册所有路由 这就是我希望自动加载工作的方式 目录/类结构示例: /app/Http/Controllers/ Foo/ BarController.php # App\Http\Controllers\Foo\BarController 如果路线是 example.com/foo/bar==App\Http\Controllers\foo\BarContr

我正在考虑在一个项目中使用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\bar控制器::add()

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

我已经找到了一种基于Opencart的路由方法来实现这一点的方法。 它们在396个控制器上有1145个不同的公共方法,这些方法都是在没有明确说明控制器和方法的情况下调用的。 这是我的尝试

.htaccess

RewriteRule^([^?]*)index.php?路由=$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 RewriteRule
响应->重定向
路由到备用控制器

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

// route overrides 
$app->get('/', 'common/home@index');
$app->get('/home', 'common/home@index');
我认为这会使应用程序运行得更快,因为它不必搜索所有注册的路由来查找匹配项,对吗


是否有更好的方法执行此自动路由过程

我认为,您可以结合Slim 3和对的支持来完成这项工作

基本战略如下:

  • 搜索每个控制器类(使用
    glob
    或自动加载器)
  • 对于每个类,使用
    ReflectionMethod::IS_PUBLIC
    过滤器调用
    ReflectionClass::getMethods
    ,以便只获取该类的公共方法
  • 使用
    ReflectionClass::getName
    获取类名,并使用
    ReflectionClass::getNamespaceName
    获取命名空间(如有必要)
  • 从名称空间、类名和方法名构建路由签名,可能使用类似的slugification库
  • 生成相应的路由
    $app->get($route\u signature,“$class\u name:$method\u name”)
  • 这是一个有趣的想法,尽管您需要非常小心,以免意外地公开任何您不希望客户端直接访问的方法。其他一些注意事项:

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

    你所做的不会让你的应用程序运行得更快或更慢,因为某些原因,人们为了优化而关注错误的事情。然而,您的想法完全违背了路由的目的。您想要定义一个路由,并且想要显式地声明将要处理它的内容。如果您试图“自动化”路由处理程序,那么您就是在实现隐藏魔法。最终,路由将与处理程序(控制器/函数)匹配。显式地说明是什么处理它会更好。这种自动化除了带来麻烦外,你什么也得不到。