sub-actions with CAction classes

Hi,

while writing an admin module I came to a wish to create sub-controllers, or sub-actions, or something like that.

I have a module "admin", with a section "rblocks".

It should have sub-section Links and Shop. I need view, add, and delete actions for both Links and Shop.

I want user to visit ?r=admin/rblocks and then browse to ?r=admin/rblocks/links.

I don’t want actions like ?r=admin/rblocks/linkAdd, I prefer ?r=admin/rblocks/links/add and dedicate all links-related actions into a single class.

But I don’t want a links module - it’s too much.

If I just make a folder admin/controllers/rblocks with controller LinksController, I can’t serve index calls, like site.com/admin/rblocks

If I make a controller controllers/RblocksController - I won’t access controllers/rblocks/LinksController, all will be caught by RblocksController class. I can set an Action class for ‘links’, but it can’t distinguish ‘links/add’ and ‘links/delete’.

I don’t want to pass action as a separate get parameter, it’s better be action in the route.

How would I do the structure for the request routing? maybe you’ll suggest an easy way?

I played with it a bit and came to a solution of the virtual paths served by action classes.

pastebin.com/MwnafYmY

My class LinksActions serves as a sub-controller, I can write actions like ?r=admin/rblocks/links/add and serve the index calls, like ?r=admin/rblocks and ?r=admin/rblocks/links.

The major limitation is that the combination of controller/action should not repeat in the URL.

Pity that CWebApplication::createController() does not store the call route to the controller, just the file path.

I can add it of course, like $this->controllerRoute = $route, but site will break on yii update.

Is there an easier solution?

what is your goal? for me it sounds you are just out for the beauty of your urls.

For that add a new rule to your urlmanager might be sufficient

The idea is to get the hierarchical structure similar to the one we have without the framework.

Not only controller/action, but controller/subcontroller/action as well.

To get several logically connected actions dedicated from the large controller into a subcontroller class, while keeping the controller functionality for other actions.

To be able take a part of a Stupid Fat Ugly Controller to a sub-structure.

The current architecture limited to module/controller/action is quite rigid.

perhaps go with:




class BaseController

{

    pubic function actionSub($act)

    {

        $this->forward(array('/sub/'.$act));

    }

}


class SubController extends BaseController

{

    public function actionDo()

    {

         ....

    }

}


Urlmanager rule:

'base/sub/<act>'=>array('base/sub'),

So you have an action inside your controller which will forward everything to the subcontroller (I think I missed the $_GET inside my example) The Urlmanager rule is just there to have it nice looking as you wished


An easier example: just to display your internal structure to the outside with a simple urlrule

so the above example without actionSub and Urlmanager rule:

‘base/sub/<action>’=>‘sub/<action>’

Another way would be to name the SubController better: BaseSubController would have the same information in the url just without the "/" (baseSub/myAction compared to your proposed base/sub/myAction)

But I don’t understand which userbase wants to have such detailed internal Information of your application… What I’ve seen is, that short and descriptive urls are more popular

Maybe you are right and I am compicating things, who cares after all.

The URL manager deserves a good descriptive article, its logic is not obvious.

Though, url mangling has a drawback of being called for each request, relative or not.

Thanks for hints.

I advice you to simply use submodule instead, you can go deep as you wish and there are no diffrerences in final results.