Extending Controllers

Hi all,

i would like to know about the best practice to seperate different sections in the yii web application

i planned to create 3 different section in my application:

  • public (where users may view the site without having to login)

  • manage (where a user may manage his post/items)

  • admin (where only the admin may enter the section)

these sections, will definitely have their own layout, their own CSSes, maybe their own javascripts, and many others custom settings (that will be best if they’re inherited from the parent controllers). so i want to make all the controllers in the site, inherited from several base controllers.

so i created 4 controllers for the base: BaseController (extend CController), PublicController (extend BaseController), ManageController (extend BaseController), and AdminController (extend BaseController).

because the default controller is SiteController, i changed the code of SiteController so that it will extend the PublicController, thus, the structure hierarchy will be like this:

  • CController

— BaseController

----- AdminController

----- ManageController

----- PublicController

------- Site Controller

but then, i faced a lot of difficulties, like:

  • even though i have put the controllers in the /protected/controllers/ directory and autoload them from /config/main.php - but they doesn’t seems to be able to be loaded successfully.

  • and even if i put the controller in the component directory (so that i can autoload them, because i failed to load them in the /protected/controllers/ directory), it doesn’t seem to be able to recognize the CController class.

  • i tried to put all the controllers that inherited from the PublicController in the /protected/controllers/public/ but when i changed the config/main.php in defaultController into ‘public/site’, it just didn’t work.

does anyone has any suggestion how an application with a structure like that should be built?

especially in the controller context, how it should be extended, and where it should be located.

how do you usually implement the section separation between public, admin, and user panel?

any references?

thanks :)

Welcome to the forum!

Try this cookbook article. You can also do it with modules. For example using the public section as the main application and for each other section you create a module. I’m currently messing around with the last solution and it works pretty good.

You have to put parent-controllers (eg BaseController) into the components folder and then import them in the config (application.components.*). Your actual controllers have to remain in the controllers directory (/protected/controllers).

Also the route “public/site” doesn’t work. In your example “public” refers to the component “PublicController” and “site” refers to the controller “SiteController” which extends “PublicController”. That doesn’t work because a route must consist of a controller and an action (eg “posts/list”). You may read this article for more info.

With modules this structure is possible:

- protected

  - components

    - BaseController.php (extends CController)

    - PublicController.php (extends BaseController)

    - AdminController.php (extends BaseController)

    - ManageController.php (extends BaseController)

  - controllers

    - SiteController.php (extends PublicController)

  - views

  - modules

    - admin

      - controllers

        - UsersController.php (extends AdminController)

      - views

    - manage

      - controllers

        - ProfileController.php (extends ManageController)

      - views

thank you for your comprehensive coverage,

the explanation in the cookbook is just what i need. still a bit confused about the scope and behaviour, but i’m sure i’ll get through it.

thanks a lot, i really appreciate it :)

For controllers you don’t have to have an action in the route as long as you have defined the default action function. The default action is what the controller will do if you specify no action at all. You also have a missing action function as well for when the app can’t find the action, by default it serves a 404 error.

You can also modify the controller map, and tell the application where to find the controller. I used the controller map to tell my app to locate a controller that’s located in my base framework.

If you have base controllers, as stated above you most likely want to put them in the components directory, though you could create a directory just for them and then import it. By default any controller that you have under the controller directory is accessable by people entering a route that would cause the application to see it. So if you don’t want the base controllers callable then this is why should not put them in the controllers directory.