Phalcon HMVC application with cross modules sub request functionality

Hi Dears, Recently there was a lot of discussions about the HMVC Pattern support in Phalcon and the ability to build multiple modules applications that support cross modules sub request during the main request.

Today I want to show you the HMVC application I built that supports all the above, it uses separate dependency injector container for each requested module as we don't need the same configuration for every module, all you have to do to request another module is this:


$result = $this->di->getShared('app')->module(
      array('param1' => 'param1_value')

Please review it at this link and give me your feedback.


Can you give an example of a situation where accessing a module from another is useful?

Yes dschissler thank you for your question, actually I have faced many situation where I needed to to reuse the results of specific module, here is some of them:

  1. If you have ecommerce website and want to reuse the (customers reviews box view) in many location like (product details page and seller page ..) just request the reviews module and send the product id in the parameters.
  2. And if you have news website and need to also reuse the (fast news bar) in many modules pages.

edited Jan '15

If you have ecommerce website and want to reuse the (customers reviews box view) in many location like (product details page and seller page ..) just request the reviews module and send the product id in the parameters.

Are you using simple views? I have a simple view folder that is in the common path.

I'm not sure but I think that these sorts of code could be put in the common/library for a project. So far I've been placing as much code as possible in each module and if it is something that will need to be reused across the system then I put it in the common folder.

Perhaps the advantage to your approach is that some classes might require specific configurations that are not relevant to the project as a whole and by accessing it externally through the module service then it would load these configurations. This is an interesting idea and I'm going to try to have discipline about maintaining the separation but as I get farther along in porting my old code to my new phalcon foundation then if I need this then I'll try to work in your approach.

Check out my Webird project. In particular notice the common/views folder. In it you will see layouts, partials and simple. Then each module has views that are only for the controller actions. You will see in some modules I load the DebugPanel that I adapted from another project. This DebugPanel reads views from the common/views/simple/debug_panel. Then this class with its views is available from any module.

So I'm not sure what the benefit of your approach is other than being able to wire in configurations but then you lose the ability to have only a single module run on a given execution and so therefore services could clash.

dschissler I liked your project and in the same time I think my approach is very useful and can achieve any goals and benefits forward like SOA, DRY code, easy caching on module level and easy to make nested HTTP caching, I deal with you that it needs more enhancement like shared view layout, and it also need better configuration on the module level.


Oof. I've been real busy traveling, preparation and jet lag. Now I'm in Shanghai!

The way that I see it since you have introduced a new type of wiring then the situation is as follows: choose one;

  • Setup modules (typically) so that exactly one is executed on a single execution. The benefit is that it can be ensured that only a single module service configuration is run on each execution.
  • Use your module service. The benefit is that cross module access is allowed and that certain classes can in essence come with a built-in configuration system. The downside is that extra care needs to be given to ensure that module services don't clash.

I propose that you consider adding a method to some level of code (Application, Module or DI ??) that first checks if DI services exist before adding them and throws an exception if they do. This would prevent unintended clashes. Maybe make the default to throw an exception and with an optional parameter can be made to override the service.

Check out how I do the view service in each Module. I define a static method in the base class that returns the view function with the specific paths defined for that module. I'm curious how your setup would implement that pathing with common layouts views.

I think that we are both pushing the module system in interesting directions and I find it likely that at least one of us will end up borrowing some implementation from the other.

For myself I'm interested in the prospect of being able to have cross module access while ensuring that the services don't clash. For the moment this means that only one View service could be defined unless the currently executing Module name/path could be sent into View/Volt service rendering process. Then the paths would be changed before each render, as that is the only difference. It starts to get real complicated though.



Perhaps the downsides of your approach could be eliminated by creating a registerSharedServices and registerUniqueServices methods. By default the approach could be to put everything into the unique part and then move things into the shared part as needed. Then the unique part (maybe better name) would only run when the Module was the first loaded and not called separately. Also it would be great to be able to ensure that the services don't clobber by default for testing purposes as discussed in my post above.

As I get deeper into my project I'm seeing the value in being able to wire up essentially a group of services at once, but its not for the reason that you use with forms because I think that my common views solution solves this better for things like many UI widgets.

I'm thinking that each module would implement a MultiModule interface that would make it impossible to do the wrong thing with the public/protected tricks in the base class.

I need to think about this for a bit and I think that I'll borrow your work and try to expand on it. It would be great to have a bit of a dialog with you here on that matter. It could be 2-4 weeks before I was able to port this work back to my Webird system for you to see though.