Weird URL and render behaviour in module

I have 2 apps in one. One is a normal website whose index.php is in /web, the controllers, modules and views are located in app/controllers, app/modules and app/views respectively. (basic Yii 2 template).

Then there’s an admin module but that admin module is not loaded in the config/web.php file. There’s another domain that points to web-admin/index.php which loades another config file (config/web-admin.php) where the module is loaded.

In that web-admin.php confi file I have the following

'controllerNamespace' => app\modules\admin\controllers,
'defaultRoute' => 'admin',
'urlManager' => [
        'enablePrettyUrl' => true,
        'showScriptName' => false,
        'rules' => [
            '<controller:\w>' => 'admin/<controller>/index',
            '<controller:\w+>/<action:\w+>' => 'admin/<controller>/<action>',
        ],
    ],

The ‘defaultRoute’ points automatically to the admin module, ‘controllerNamespace’ points to where its controllers are and the urlManager has 2 rules. If there’s only a parameter, that’ll be the controller and it’ll point to admin//index. If there are two params, the first one is the controller and the second one is the action.

Everything seems to work fine but in some cases it doesn’t.

Example:

  • web.test/client/index → works, it points to app/admin/controllers/ClientController::actionIndex(). Loads view app/admin/views/client/index.php
  • web.test/client → doesn’t work. Points to the correct controller but tries to render a view from app/views/client/index.php

During some tests and changes, web.test/client worked but web.test/client/ didn’t. I don’t know why the / made it crash, but now it crashes always because it doesn’t find the correct view.

In the Module.php init() method I have set $this->viewPath = Yii::getAlias(’@app’) . ‘/modules/admin/views’; but doesn’t change anything.

So, depending on the route, the app checks for one viewPath or another.
I can force the view in the action: $this->viewPath = Yii::getAlias(’@app’) . ‘/modules/admin/views/client’; but then I have to force the layout because it tries to find the one outside the module.
I can’t set the public properties $viewPath and $layout. Well, I can but it doesn’t work. The solution I came up with is creating a controller from where all the others extend with a beforeAction() method that sets the layout and the viewPath with the controller name ($this->id).

But I feels something is wrong here. I’m missing something and I don’t know if it’ll make my app crash. Also I don’t know why the public properties are not working. It doesn’t matter if I set them up from the module or the controller.

I’ll be thankful if anyone sheds some light on this.

should be

'<controller:\w+>' => 'admin/<controller>/index',

\w+ is a regular expression matching one or more characters in the character class \w, which is a shorthand for [A-Za-z0-9_], see Regexp Tutorial - Shorthand Character Classes

1 Like

Yes, thank you.

That’s how I had it before and I deleted it accidentally when I made some changes. In my previous message I wrote

During some tests and changes, web.test/client worked but web.test/client/ didn’t. I don’t know why the / made it crash, but now it crashes always because it doesn’t find the correct view.

That’s what’s happening now that I fixed the regular expression. web.test/client works but web.test/client/ doesn’t.

regarding the slash, see Handling Requests: Routing and URL Creation | The Definitive Guide to Yii 2.0 | Yii PHP Framework for how this is handled.

1 Like

That fixed it, thanks.

I actually tried it a couple days ago but I probably messed up somewhere else and it didn’t work.

The only thing that is not working as I want is the URLs that contain a hyphen. I guess \w+ works only for alphanumeric strings, so if there’s an action called actionUpdateDetails the URL will be web.test/admin/client/update-details instead of web.test/client/update-details.

Do I have to use a full regular expression there to make it work?

If you want hypens, you need to add them to the regex: '<controller:[\w\-]+>' => 'admin/<controller>/index',

1 Like

Thank you (L)

It works flawlessly.