I’ve been thinking a lot about the way I currently use the view in my MVC applications. I’ve come up with some questions that I can’t find much information about.
The first question is about the relationship between the view and the controller. I’ve noticed frameworks such as ZF and Rails use a 1:1 relationship between the view and an action, whereas other frameworks use a 1:1 view controller relationship. So the question is what are the pros and cons of each approach?
This next question is more-so about layouts. As a layout is generally built out of multiple views, it will often be necessary to dispatch to multiple controllers, but how should this be done? Are there any best practises? In the past I’ve always separated my controllers into action and module controllers. The front controller would dispatch the action controller, then based on a configuration file would dispatch to the module controllers. The corresponding views would all then be passed to the layout. Is the a good way of handling this?
That makes perfect sense, it’s similar to what I already do. ATM I set the _toString() value of the views for each action as named and ordered parts of the body in my response object. Essentially I’ll be changing this so the views (objects rather than string values) are passed to a layout model and the layout view is set as my response body.
Would it sensible for the layout model to take values for the layout view e.g. setting things like css, js, meta-tags etc. or is this just going to be mixing the concerns of presentation and domain logic too much (I suspect it is)?
Regarding the Front Controller and domain logic, I tend to use extremely slim FCs, all the work is done by the request, router, dispatch and response objects. The FC just sets up these models and returns the response to be rendered in the bootstrap.
Would it sensible for the layout model to take values for the layout view e.g. setting things like css, js, meta-tags etc. or is this just going to be mixing the concerns of presentation and domain logic too much (I suspect it is)?
That’s one way of doing it. The other way is to allow each view to specify js/css it requires, then when a view is added to another view, the parent inherits the requirements. The way you mentioned is probably better though, as each view doesn’t need to know of the layout that it could be used in why should a view care about the page title/meta tags?
Not sure I like the idea of repeated controller code, the problem is if I decide to make changes later, not only will I need to make them in multiple locations, those locations wont be clearly defined.
Would it make sense for the layout view to be rendered by the front controller? That way the Front Controller can dispatch to the routed Action Controller, then (based on some sort of configuration) dispatch to Action Controllers for smaller modules like menus, then pass all of the resulting views to the layout view, before finally rendering it all.
It seems to make sense but not sure if there are any important considerations that I’m not taking into account.
Edit: just though of the view helpers, the layout will likely have some helpers for setting css, scripts etc… all of the views would need access to these helpers. The first solution that pops into my head is to make the layout an observer.
So instead of dispatching to a default action you just get the controllers view? Surely in most cases you will need a default action anyway to set up the model?
I’m not sure what you mean by layouts being their own MVC triad. Are you saying that a layout controller would return a view (for the layout templates) and that view would (though some configuration) would fetch the other needed view by calling their controllers? Hope that makes sense?
So instead of dispatching to a default action you just get the controllers view? Surely in most cases you will need a default action anyway to set up the model?
Depends on what the view is doing, if you’re doing anything complex like sorting, fetching specific data then you do need to call a controller action to set this up, but this presents another potential issue with separation of concerns: should a single method in the controller have two responsibilities; selecting a view and configuring the model? Where there are no specific constraints the whole triad can be used without any config.
I’m not sure what you mean by layouts being their own MVC triad. Are you saying that a layout controller would return a view (for the layout templates) and that view would (though some configuration) would fetch the other needed view by calling their controllers? Hope that makes sense?
Yes, ideally the view would contain other views (called subviews) any actions performed on these views would be done on their corresponding controller. However, it’s often better for the view to initialise the entire triad via the controller so it can set the view’s state via the controller.
The first question is about the relationship between the view and the controller. I’ve noticed frameworks such as ZF and Rails use a 1:1 relationship between the view and an action, whereas other frameworks use a 1:1 view controller relationship. So the question is what are the pros and cons of each approach?
Fairly straight forward. If a controller is creating views you need this logic in each controller action, resulting in repeated code. With a 1:1 relationship you don’t need the repeated code but you do need more controllers but you don’t need a default controller action to initialise the view.
Imho, repeated code is worse because if it ever changes you have to change it in each controller action or, in some cases, the need to call a controller action to make something happen.
Consider:
$controller = new MyController;
If I wanted to include the output of this controller in a different view (your question about layouts is this. A layout is essentially just a special type of view) I could. either way, however without a 1:1 relationship each time I do this I need to do:
$controller = new MyController;
$controller->showList();
return $controller->view->output();
instead of
$controller = new MyController;
return $controller->view->output();
Again it’s fairly trivial but repeated code is problematic at best.
1:1 will result in more classes defined, but these will be more specific.
On layouts, I’ve just always considered them their own MVC triad. The view pulls in other views. Imho, a layout controller and view should be no different than a ‘normal’ controller and view.
Yes the layout should probably be the view associated with the front controller. The front controller can then initialise the other controllers and call the requested action.
The problem, then, is how can the layout view know of its subviews? Either the front controller has to push them to its view or there needs to be a model which deals with storing the relative parts required by the layout and then have the layout view request the application view from the model.
I believe a model to deal with this is better. So the application flow would be:
-Request is sent to front controller
-The front controller tells its model which controller to create [app controller could be created in the front controller, but it would be useful to make this logic more reusable]
-The front controller’s model passes the request to the app controller and calls a controller action if required
-The layout view requests the current sub-view from its model
You could argue that having a model know about a view goes against MVC (where models should never know of views or controllers), however, the “business logic” of the front controller is creating other controllers. This completely belongs in a model. After all, which app controller is used is setting the state of the application and any kind of state should be stored in a model.
Well with a 1:1 relationship you remove the double call to the controller avoiding those issues, which is why i prefer it You can update the the model used by the subview from the parent controller. This means the view is only including a view. Which makes more sense but may cause minimal repeated controller code because now the code to update the model is happening in 2 controllers. Which may or may not be preferable (separation of concerns vs repetition).
edit: The layout is just another controller/view pair. It should be treated no differently than any other view, imho.
Would it make sense then to enforce a convention whereby the action is dispatched to set up the model, followed by a second dispatch on the controller to set up the view?
Ok, that kinda makes sense, but I’m still a little unsure as to how it would work. I envisage the flow as something like; the Front Controller dispatches to an Action Controller, firstly to set up the model (we’ll call the action listAction()) and then a second time to set up the view (we’ll call the action viewAction()), viewAction() may return a view that uses several sub-views - so would be responsible for instantiating the sub-view’s Action Controller, invoking viewAction() and setting the sub-views to the view?? At what point does the layout fit into this? I’d really appreciate some code to clarify this.