mae
mae

Reputation: 15666

Yii2: Omit controller ID from module route

A typical Yii2 route to any action in a module controller is as follows:

<moduleID>/<controllerID>/<actionID>

How do we configure/structure our module (which has only 1 controller) so that we may reach its actions directly using the following route:

<moduleID>/<actionID>

without having to override the routes in the main application's urlManager?

Upvotes: 1

Views: 754

Answers (3)

mae
mae

Reputation: 15666

Combining the answers from Bizley and IStranger and and adding some of my own wisdom I have come up with a solution. As long as your module is being added through composer, this is what you can do:

  1. In your module create a RouteBootstrap.php file with the following content:

    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>'],
                ]);
            }
        }
    }
    

    (be sure to replace moduleID with you actual module ID). This is the same technique used by the official Yii2 Gii module.

  2. Add the following to your module's composer.json file:

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

    More details about this trick are described in the documentation.

  3. Remove the module from your vendors directory and run composer update.

That's it. Your module will automagically add the route rule to the main app and you will be able to access the DefaultController's actions using <moduleID>/<actionID> routes.

On the other hand this is still not the ideal solution. It is more of a workaround to Yii2's design flaw. If someone comes up with a better solution, it will be set as the accepted answer.

Upvotes: 0

IStranger
IStranger

Reputation: 2051

Additionally to Bizley's answer you can create in your module separate config-file with module-specific url-rules, for example:

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

Then load these rules in module bootstrap method (as show Bizley). Then you can in main application automatically scan available modules and similar config files, and merge these url rules with common application config. Moreover is important to prevent duplicattion these rules when module will loaded.

I do not like this approach, because it broken the "modularity", however it will work without bootstrapping of all modules (this is very keeps memory).

Upvotes: 1

Bizley
Bizley

Reputation: 18021

If by "without having to override the routes in the main application's urlManager" you mean not modifying the urlManager routes I think it's not possible.

But if you only mean "without new route rules added in app's configuration file" here is the way:

You can do it by setting rules inside the module.

Add your module to the bootstrap section of configuration if it's not there yet.

Now in the main module's file (default Module.php) add:

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

Upvotes: 1

Related Questions