Proposal for Module Support

Currently, the module concept in Yii is very vague and is often mixed with the extension concept. In this proposal, I will try to clarify it and call for feedback on possible support for module.

Definition of Module: A module a self-contained sub-application consisting of one or several controllers together with their supporting files, such as views, models, libraries. Users can interact with a module through its controllers and actions.

Why Using Module: In a large system with tens or hundreds of controllers, it is more manageable to divide the application into modules, each being developed and maintained by a specific group of people. In an open system like an open source CMS, module serves as a way to add big chunks of functionalities. For example, there could be a forum module, a RBAC management module, etc.

How do we support module: Currently, I have the following in mind:

1). Each module is organized as a separate directory whose name is the module name

2). All modules are placed under the "/protected/modules" directory.

3). The directory layout of a module is similar to that of the "protected" directory with "controllers", "models", "views" and so on.

4). A module needs to be "installed" in order to be usable in the application. This could be done by declaring the module name in the "modules" property in the application configuration.

5). A module can have its own configuration file (??)

6). Accessing a controller in a module is like accessing the controller in a subdirectory of "controllers". The module name should be used as the prefix to the controller ID. For example, "index.php?r=forum.post/view", where "forum" refers to the "forum" module.

What else? Do we need a module object for each module? The module object is like the application object. It contains some global information shared by controllers under that module.

What about theming?

Hi Qiang,

I unreservedly support implementing modules as it would greatly increase the possibilities, whilst still maintaining a manageable application structure.

It would be interesting if each had its own config file, increasing the control over separate parts of code.

I agree with the initial specs… here's additional food for thought:

  1. I know we want to steer away from dependency hell, but support for module dependency could be added to the module config file.

  2. Which brings us to support for module versions as well - can we have that added to the specs? Traditional X.XX format could be appropriate.

  3. Theming: main app layout, module layout and views? That way it'd be easy to create subs menus specific to each module.

More to come once the discussion heats up!

Cheers

Cass

I get a flashback now to modules in PRADO 2. In PRADO 3 the module concept was removed and grouping of pages into directories was it replacement. That way you could add as many level as you wanted.

Because of the naming schema controlledID/actionID we need to think about how to group them into "modules".

In Yii it's possible to add sub-directories into controllers/ to that you can have:

index.php?r=forum.posts/list

index.php?r=blog.posts/list

and adding some rules to urlManager you can easily have:

forum/posts/list

blog/posts/list

This is good enough in most cases I guess.

When it comes to an actual implementation of a real module concept in Yii I agree with 1-6 of qiang's proposal - it's pretty much in line with what I had in mind. I also see a CModule-class coming.

I need a real life example of module dependencies to have any opinions about it.

A module should adapt the application theme and bundle needed assets (with the possibility to override styles from the application if needed).

A module should sit within the $content of the application layout. (a bit unsure about this one, may be redefined)

  1. It would be nice to have modules within modules. That way some kind of modules would be able to have plugins.

For example, I have an admin module, and a forum module. In the forum module I have an admin submodule that works as a plugin to the former admin module.

Another example, I have a webshop module, and for that module I would like to develop several payment gateways, which could be submodule plugins.

  1. If a module always is printed in the views $content variable, I think would be a huge drawback. I think the developers would loose a loot of freedom in what we would like the modules to behave.

  2. Module class? I t could be smart to have a class where you could import localy, like: Yii:import('module.controllers.MainController'). where "module" refers to the local module.

What's being discussed here are programmer's modules–discrete units of code that can, for example, be developed independently or semi-independently.

I am (just starting) to write an application that will have user's modules–discrete sets of functionality.  The idea is to have allow the various functionality sets to be enabled or disabled allowing the user to configure the app to have varying sizes and levels of complexity.  To use a bad analogy, it would be like word processor that could look like MS WordPad or MS Word or somewhere in between.

Programmer's modules sound like they would be helpful in implementing up user's modules.  Do you have a target release in mind.

The modules directory should be located outside of the protected (application) directory and a module would be considered as an application in its own right.

A module object seems to be a good option.

3rd party modules would not then interfere with the development (upgrades etc) of the main application.

Maybe we can create some interfaces to make some interaction between modules and the application.

Another way is just to creat a type of application that is just a module container something like CModuleApplication << CApplication that have some diferent module data and load some modules configurations (the ones that must be used) and viceversa, read some of the application data from modules.

A solution is to have an module directory outside of the app and framework directory, but also allow a modules directory in the app. In that way a module could be added globaly on the server or in the application. And the import function could first look into modules in the app and then globaly.

Your proposal looks good. I think a module object would work, for configuration or even dependency management. The only thing I would change is the routing of forum.post/view, I would rather do it like in Zend Framework. For example you register a route with a module

$route = new Zend_Controller_Router_Route(


    ':module/:controller/:action/*',


    array('module' => 'default')


);


$router->addRoute('default', $route);


The ‘default’ module is the application. If you would visit ‘forum/post/view’ you’d get to get to the forum module. Similarly you could register a route without the :module parameter and still direct the url to a module. Overal the implementation of routes in ZF seems pretty solid

While I know I’m a newcomer, I strongly support everything suggested here. Particularly Module’s for Modules ETC. This would immensely reduce the workload on individual developers who (like myself), Are the only people competent enough to modify the core code. This allows me to have other devs manage different parts of the system while still keeping things organized. (And if i sound like an ass, I just don’t like worrying about other peoples code buggering things I’ve spent hours on. >.> I really am a nice guy. ^_^)

Hi

Some thoughts…

I don't think dependency should be part of a module makeup, but it should provide a class which Yii (or another module) can query for version (or other) information. So if Yii could have something like CApplication::getModule("name") and that returns an object implementing an interface like getModuleVersion() or getModuleAttribute("version") that should provide enough of an interface so one module can check a different ones version…

Themes should be implemented in a similar manner  like themes/classic/modules/MODULE/views/ …

nz

Qiang,

I really think modules should be part of the framework.  Your proposal makes sense and it falls along the lines of how this modular extension works similar to the CI one built by wiredesignz.

http://codeigniter.c…ensions_-_HMVC/

----A module needs to be "installed" in order to be usable in the application. This could be done by declaring the module name in the "modules" property in the application configuration.----

It should also support runtime installation, for example if we wanted to build a CMS where modules can be installed by the end user. 

Theming…I feel in most cases modules would just inherit the application theme or be able to override and use its own.  Usually small sites that have these modules (like members, blogs, articles) would have same consistent look as the website theme.     However, some large sites like Yahoo may have different themes for its modules. 

I just checked in the support for application modules (1.0 branch). Could you please help me to test it and give me your feedback? Thanks.

You may start with the "yiic shell" tool and use its "module" command to create a module under your existing application.

Nearly every feature proposed in this thread is implemented. You can have nested modules, very flexible control of module view layout, module configurations, and so on.

The URL syntax is very natural. Assuming you have a module A which has a submodule B which has a controller C and action D, you can access this action with the following URL:

/index.php?r=A/B/C/D

Controllers can still be organized in subdirectories, like we did before. In the above example, if controller C is located under path/to/C, then the URL becomes:

/index.php?r=A/B/path/to/C/D

Note, a module needs to be "installed" before it can be used. To "install" a module, simply declare its ID in the "modules" property of the application (or the module in case of using a sub-module).

Great, I hope to test it out this weekend. I’ve got finals this week  :(

Hi

Quick question, how can the "Main" applicaiton know what "modules" are installed ?

A call to Yii::app()->getModules() yields an empty list unless you call a module explicitly first like Yii::app()->getModule("MiniMe").

My configuration file is simply

    'modules'=>array("MiniMe"),

Thoughts ?

nz

Just modified getModules() which should return the stuff you want now.

opps !

Missing semicolin line 569 CWebApplication

nz

Fixed. Thanks!

Added a module to the blog demo and discovered that CController.php line 726, $module->getId() is returning the WebApplication object "md5($name)" causing the routes to be prefixed by the hash incorrectly as if WebApplication was a Module.

Thanks. Fixed.