PHPackages                             morket/hmvc-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. morket/hmvc-bundle

ActiveSymfony-bundle[HTTP &amp; Networking](/categories/http)

morket/hmvc-bundle
==================

Symfony2 Bundle providing a fast Hierarchical Model View Controller (HMVC) solution utilizing Symfony's dispatch flow

0.2.2(13y ago)7303MITPHPPHP &gt;=5.3.3

Since Feb 11Pushed 13y ago1 watchersCompare

[ Source](https://github.com/Morket/HMVCBundle)[ Packagist](https://packagist.org/packages/morket/hmvc-bundle)[ Docs](http://morket.github.com)[ RSS](/packages/morket-hmvc-bundle/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (4)Versions (2)Used By (0)

Morket's HMVCBundle (ALPHA, in development)
===========================================

[](#morkets-hmvcbundle-alpha-in-development)

[![Build Status](https://camo.githubusercontent.com/9788f366d1ea5bf3ebe0626bd6c79fbf330dfbfb698eaf445c6cd20608377712/68747470733a2f2f7472617669732d63692e6f72672f4d6f726b65742f484d564342756e646c652e706e67)](http://travis-ci.org/Morket/HMVCBundle)

Why are external application calls using a RESTful interface while internal application calls consist of many custom Model methods? Why are internal services different from external services? They shouldn't. The current web is a cloud of services, now your application can be as well.

The HMVCBundle is a Symfony2 Bundle providing a fast Hierarchical Model View Controller (HMVC) solution utilizing Symfony's dispatch flow to call internal services in the same way you would call them externally. It integrates fully with RESTful and non-RESTful controllers from FOSRestBundle, KnpRadBundle and native Symfony.

Concept
-------

[](#concept)

A lot has been written about the Model View Controller pattern and the fact that all your business logic should be put into the Model layer. Conceptually this is totally true, but practically it can be a pain in the ass. A lot of development time goes to mapping Controller actions to Model objects and methods. A lot of time is spent on deciding where to put code and how to structure it well. Where do I put my Forms? Shouldn't I validate from the Model layer as well? If I use annotations to validate my GET and POST values, shouldn't I validate the entity again in the Model layer? Why does my Controller have create/read/update/delete methods mapping to create/read/update/delete methods from my Model layer?

Our statement is that Model View Controller is not that suitable for modern web development and it's outdated. Problem #1 is the fact that there are no real events fired from the View layer, which makes every request just a single application flow. Problem #2 is that we prefer convention over configuration these days, making our Controller layer extremely predictable and repetitive.

We aim for a Presentation Abstraction Control (PAC) approach of web development. Look at a Controller as an entrance to one service within your application. See it as a Control element handling flow, rather than application logic. Your Control layer can call a Form or Doctrine Repository directly, it can perform validation and it can have some business logic. When it gets complex, naturally you will write Abstraction classes to solve this complexity. PAC encourages this. Your Presentation layer will be used for template rendering or serialization (to JSON/XML for example). A template within the Presentation layer could or could not call another Control element to present some extra stuff, like a logged in user on top of a page.

Each service is a MVC/PAC 'island', or triad. You could have a User service and a Product service, who always call each other via the Control element of the service. And because the Control layer is implemented as Symfony2 Controllers, they are also callable from the outside. Using RESTful Bundles like FOSRestBundle or KnpRadBundle, you automatically create an internal and external RESTful API to all your services.

[![Presentation Abstraction Controller image](https://camo.githubusercontent.com/dc532209c9034b7cf9f589c13e88690ea39b0c117fff1e8ce1342357bc82030b/687474703a2f2f75706c6f61642e77696b696d656469612e6f72672f77696b6970656469612f636f6d6d6f6e732f342f34612f5061632d736368656d612e706e67)](https://camo.githubusercontent.com/dc532209c9034b7cf9f589c13e88690ea39b0c117fff1e8ce1342357bc82030b/687474703a2f2f75706c6f61642e77696b696d656469612e6f72672f77696b6970656469612f636f6d6d6f6e732f342f34612f5061632d736368656d612e706e67)

How HMVCBundle works
--------------------

[](#how-hmvcbundle-works)

The HMVCBundle uses Symfony's normal Request handling flow to make internal calls. It returns the returned data from the Controller and makes it available elsewhere. It's quite simular to Symfony's forward method, but without the whole HTML/JSON/XML rendering process. Currently using the HMVC trait (PHP 5.4+) adds one method to controllers:

```
$this->call($route, $attributes = array(), $data = array(), $query = array(), $rawResponse = false)
```

ParamExplanation**$route**is the Symfony route**$attributes**are request/route attributes, which are defined as parameters in your Controller action methods**$data**is POST data**$query**is an array of query params ("GET params")**$rawResponse**will force HMVC to return a Symfony2 Response object instead of returning the data directlyYou can still use your own Controllers, Event Listeners, Views, Templates and Serializers. The HMVCBundle won't affect normal behavior, it will only add functionality for internal requests.

**PHP 5.3: morket\_hmvc.agent**

You could just call the service **morket\_hmvc.agent**, which has the same call() method as documented above. It works exactly the same as the trait described in this README. Good examples will be added shortly.

**kernel.view event**

The Bundle WILL probably and SHOULD block your kernel.view (onKernelView()) events when making an internal call. This is necessary to make sure no HTML/JSON/XML is rendered for internal (HMVC) requests. The kernel.view event is defined with priority 128, so it will block FOSRestBundle's and KnpRadBundle's kernel.view events, but you can still out-prioritize it. This is native Symfony behavior, Symfony will always allow only one kernel.view per (sub)request, because output can only be rendered once. (Note: kernel.view is fired when a Controller returns something else than a Response object, like an array of data or a View object)

**Exceptions**

When doing an internal HMVC call, any thrown Exceptions will be thrown through, meaning you can catch them in the Controller where you make the call. See examples below.

How to use it
-------------

[](#how-to-use-it)

Just use the trait Morket\\Bundle\\HMVCBundle\\Controller\\HMVC in each Controller you want to make calls from. That's all. HMVC won't affect existing software in any way. You can partially use HMVC, or include the Bundle and not use it at all. It won't break stuff.

**Simple example without dependencies**

```
