Multi-level navigation & Controllers...

Hi,

I’ve posted this in the Installation & Setup forum, but after some thought that might not be the correct place for it! So I’m sorry for the duplication.

I’d basically like to create a multi-level structure within Yii, to allow long URLs like ‘/page1/page2/page3/page4’. I’ve come up with a solution, but I’m sure there’s a better way of doing it. Please allow me to explain the setup.

I have a default install of Yii running, using the yiic webapp command. The usual URLs work, like ‘http://localhost/site’, ‘http://localhost/site/login’ etc, which are all run from the same default ‘SiteController’.

I’ve created a new controller called ‘TestController’, and placed it under ‘/protected/controllers’ and when I visit the URL of ‘http://localhost/test’ it works as you might expect.

But here’s what I’d LIKE to do:

I’d like to create a directory structure like this, accessible using URLs that correspond to the Controller name:




/protected/controllers

    SiteController.php

    /site

          TestController.php < http://localhost/site/test

          NewsController.php < http://localhost/site/news

          /news

               ContactController.php < http://localhost/site/news/contact

          EventsController.php < http://localhost/site/events

          /events

               ArchiveController.php < http://localhost/site/events/archive



I’ve tried creating a ‘/protected/controllers/site’ directory and placing ‘TestController’ in it, but I get the error:


The system is unable to find the requested action "test".

This is because Yii is running the ‘SiteController’ (because the URL is ‘/site/test’) and looking for an Action called ‘test’.

But I don’t want Yii to look for an action of ‘SiteController’, I want Yii to look for a Controller called ‘TestController’ and run that instead of ‘SiteController’ to be it’s own self-contained Controller that merely sits underneath the ‘site’ directory.

Now, I’ve managed to come up with a solution, but it’s not ideal. I’ve set the directory structure up like so:




/protected/controllers

    SiteController.php

    /_site

          TestController.php < http://localhost/site/test

          NewsController.php < http://localhost/site/news

          /_news

               ContactController.php < http://localhost/site/news/contact

          EventsController.php < http://localhost/site/events

          /_events

               ArchiveController.php < http://localhost/site/events/archive



And I’ve added rules to the urlManager, like so:




       'urlManager'=>array(

            'urlFormat'=>'path',

            'showScriptName'=>false,

            'rules'=>array(

                '/site/<controller:\w+>'=>'/_site/<controller>',

                '/site/news/controller:\w+>'=>'/_site/_news/<controller>',

                '/site/events/controller:\w+>'=>'/_site/_events/<controller>',

                '<controller:\w+>'=>'<controller>',

            ),



So the URL manager takes care of the URLs for me, but if the site gets big it may become cumbersome to manage - but it allows me to drill down as far as I need to. Maybe there’s a way I can attach a new behavior to a piece of code that, if it fails to find an action, it looks for a controller at that level instead?

Is there a better way of doing this?

Thanks in advance.

Sorry, I just want to re-ask this? Has anyone tried creating long URLs as mentioned above?

Thanks!

Your problem is because you have both a SiteController.php and a site sub-directory. In this case, the former takes precedence when your URL starts with "site".

Thank you for responding qiang.

I’m aware that this is the issue, but what I’m asking is how would I go about getting around this issue? I’ve come up with a solution, but I’m sure someone must have encountered this before and created a better solution.

Site structures can be fairly complex, and there’s often a need to create a URL that has a few levels of structure. All I want to run the LAST part of the URL as a Controller.

So if I have a URL like ‘http://localhost/level-1/level-2/level-3/level-4’, all I want to do is just have the ‘level-4’ part of the URL taken as the name of the controller. I don’t care in this case about level-1, level-2, level-3 - they’re just part of the URL that allow me to structure my site.

And if I visited ‘http://localhost/level-1/level-2’ I’d want the ‘level-2’ controller to be run.

Am I making sense?

What qiang is saying is that what you are wanting doesn’t work because you have both SiteController.php and a folder called site.

Have one or the other eg.

SiteController.php and /sites/

or

SomethingController.php and /site/

Understand?