multiple (loosly coupled) modules building up a common (global) navigation menu

After inspecting a little bit Yii’s internals (because of this problem), it seems CController::forward()'ing to another module/controller/action from within the application’s layout leads to endless recursion, which is pretty understandable.

(But forget about that problem, as …) However I feel (note the subjectivity here) I’m doing it wrong. I (will) have some loosely coupled modules (which can act as standalone applications) and I want them all to store something in a common place, a variable, a component or something, so that I can have a common navigation menu throughout the site, with all the links generated by each module.

Considering that loose coupling is VERY important to me, what is the best way to achieve that?


Sorry, I’ve forgot to say that there may be loose dependencies among modules. A module may decide, when noticed by another module, to do or not to do (eg to add a link to the global navigation) something. Also note, there may be circular dependencies: module A request module B some info, then A tells back B to add the “feature” or not to the “navbar”.

Of course, I’m oversimplifying the problem. It may be anything, not just a “navbar”. It may also be a storage for objects for another module, for example an administration panel.

Luckily, circular dependencies won’t need more than a full handshake (as in networking terms), that is, there will be at most three calls between two given modules A and B which negociate a feature.

To make a common menu you can create a widget (it can also extends CMenu widget) and rewrite it’s run() method. This method should walk through all modules and call each module’s method generateLinks(), for example. And then just render a menu based on these links (links can be an array, strings or any other type).

In the general case there can be many approaches. You can create a component, an application component, or a module to manage other modules.

In general, if you want modules to communicate you need to build an API for each module which provides the functions available to other modules.

So module A (which is defined as "class A extends CModule") could provide the following APIs:



I’ll go with the “application component” way, because I intend to do it really reusable: the application component will simply store chucks of data. The actual widget will be created by views based on a specific chuck.

Some time ago (years) I was active on the Horde project(s)… I seem to remember they had a way of declaring a ‘provides’ section. If you have a common API for all your modules they would register themselves (dynamically or via a config file) into the current application (where an application is made up of modules).

In this way any Module could ask the Application: “Is ‘function|service|module’ ‘present|active|provided’?”, and deal with the result - e.g. check for the existance of a certain method, etc.

This would enable you to package any number of modules into an application, and they would simply behave well, and play nicely with other modules in the app.