Let’s once again discuss the topic which seems to be quite popular here. Calling actions of one controler inside another contoller.
Example web portal:
-
Home page
-
Some static pages
-
Forum: nested forums list, threads list, posts list, admin interface etc.
-
Submissions by users: submissions grouped by users, latest submissions, highlights etc.
-
Journals: journals of a user, latest journals etc.
-
User management: register, login, admin interface
-
etc.
Goal: Home page must include: static info, latest submissions, latest journals, latest forum posts. User page must include info about the user, his latest submissions and journals.
How do I do it?
The most simple answer is that I’d like to include on my “user/view?name=username” page this stuff: “forum/posts?sort=date&user=username”, “journals/view?sort=date&user=username” etc. So that UserController.actionView method called a few renderPartials and then render primary view. But… I can’t do that.
- The most popular suggestion seems to be to use widgets. I’m newbie, I haven’t written that much code using Yii, but widgets look like rather small pieces with one contoller, single action, usually one view. They’re like controls. Widget is what often called a “control”.
I can’t make forum a widget, forum would too heavy concept for a widget, wouldn’t it? I would also lose all the nice stuff with url management, actions and other goodies from Yii.
- Another popular suggestion is to put everything necessary into one controller, to use very fat models so that code in controllers is almost unnecessary.
The problem is, I don’t want to touch too much from forum classes in my user classes. Instead of input parameters (controller-action pair, its arguments) I’ll need to know about models, about model’s methods and properties, about view etc. Even if model is really fat and I just need to call a few methods, that would still be copy-and-paste, that would be unnecessary coupling. Whenever I change ForumController.actionPosts I’ll need to remember to modify UserController.actionView too and vice versa. If I need to refactor forum classes, I’ll need to refactor UserController too. Considering how bad refactoring tools for PHP are (compared to C#, Java etc.), it would be much harder.
- Heard another suggestion too. To use AJAX and to load content dynamically. Absolutely not an option. This solution makes indexing by search engines impossible. What’s the point of having a site with content which nobody can find?
4a. Hacky solution. To call CWebApplication.createController, runController. This way, we can use controller and its actions without worrying about their internals. However, we lose possibility to pass arguments. Both CUrlManager and $_GET will contain information for parent page, so we’ll have to find another way to pass arguments. And to tell that we only need partial renders too.
4b. Variation of the prevous hacky solution. Modify $_GET and make CUrlManager parse URL again. Now, we’ve got controllers, actions and arguments. It finally works! But… I feel dirty.
What is the true way?