Yii2:从模块路由中省略控制器 ID

Yii2: Omit controller ID from module route

模块控制器中任何动作的典型 Yii2 路由如下:

<moduleID>/<controllerID>/<actionID>

我们如何 configure/structure 我们的模块(只有 1 个控制器),以便我们可以使用以下路径直接到达其操作:

<moduleID>/<actionID>

无需覆盖主应用程序的 urlManager?

中的路由

如果 "without having to override the routes in the main application's urlManager" 你的意思是不修改 urlManager 路由,我认为这是不可能的。

但如果你只是想说 "without new route rules added in app's configuration file" 方法如下:

您可以通过在模块内部设置规则来实现。

将您的模块添加到配置的 bootstrap 部分(如果尚不存在)。

现在在主模块的文件中(默认 Module.php)添加:

public function bootstrap($app)
{
    if ($app instanceof \yii\web\Application) {
        $app->urlManager->addRules([
            ['your-module/<action>' => 'your-module/controllers-name/<action>'],
        ]);
    }
}

除了 Bizley 的回答之外,您还可以在模块中使用特定于模块的 url 规则创建单独的配置文件,例如:

modules/<moduleID>/config/url-rules.php

然后在模块 bootstrap 方法中加载这些规则(如 Bizley 所示)。 然后你可以在主应用程序中自动扫描可用模块和类似的配置文件,并将这些 url 规则与通用应用程序配置合并。 此外,在加载模块时防止重复这些规则也很重要。

我不喜欢这种方法,因为它破坏了 "modularity",但是它可以在没有 bootstrapping 所有模块的情况下工作(这非常节省内存)。

结合 and 的答案并加入我自己的一些智慧,我想出了一个解决方案。只要您的模块是通过 composer 添加的,您就可以这样做:

  1. 在您的模块中创建一个包含以下内容的 RouteBootstrap.php 文件:

    namespace your\name\space;
    
    class RouteBootstrap implements \yii\basic\BootstrapInterface {
        public function bootstrap($app) {
            if ($app instanceof \yii\web\Application) {
                $app->urlManager->addRules([
                    ['moduleID/<action>' => 'moduleID/default/<action>'],
                ]);
            }
        }
    }
    

    (请务必将 moduleID 替换为您实际的模块 ID)。这是Yii2 Gii官方模块使用的same technique

  2. 将以下内容添加到模块的 composer.json 文件中:

    "extra": {
        "bootstrap": "your\name\space\RouteBootstrap"
    }
    

    有关此技巧的更多详细信息,请参阅 documentation

  3. 从您的 vendors 目录和 运行 composer update 中删除模块。

就是这样。您的模块会自动将路由规则添加到主应用程序,您将能够使用 <moduleID>/<actionID> 路由访问 DefaultController 的操作。

另一方面,这仍然不是理想的解决方案。它更像是 Yii2 设计缺陷的变通方法。如果有人提出更好的解决方案,它将被设置为已接受的答案。