In my recent post regarding the Model Service layer, there was one query about me mentioning that the View is configured by the Controller which goes against the grain of traditional MVC idea of “Views Should handle their own Models / data”.
There is nothing wrong with Views being able to handle their own models, I’m not suggesting that this shouldn’t be the case. You can also do it this way. That is the “traditional MVC” way of doing things and it works fine which is why I’m questioning why I’ve moved away from it. I’m just typing as I go so hopefully by the end of it, we’ll have something that makes a point.
I used to Really love this sh*t!
I used to trumpet the sh*t out of this because I had it figured out and it made me feel smart
. I thought hey, I can adhere to the traditional MVC way of things and make the View select it’s own Model (or models) and gather information on it’s own – all I need is a View Helper. Further along came the question “What about the times when the Model needs to be used by the Controller?” well I got a plan for this too, then there’s the “What about when the Controller and View need access to the same model?” case. I needed to create a strategy to make sure that the Model isn’t instantiated twice in these cases.
This is how I did it: Components you need to code up to make it so that the View can choose it’s own Models
Step 1: I created a Model Service Factory which I stored in Zend_Registry – the Model Service Factory has a Registry of it’s own and checks to see if an instance of the Model being requested already exists – if it does, it returns that instead of creating a new instance.
Step 2: I created a View Helper called “GetModel” which accesses the Zend_Registry to access the Model Service Factory and returns the model
Step 3: I then created an Action Helper called “GetModel” which worked exactly like the View Helper.
But then, I found myself questioning if the view selecting it’s own models / data applies to PHP, or if all this complexity is worth anything useful aside from saying “I can do it”. Here are some of the things I’m thinking about:
- One of the cases that I’ve found cumbersome is when I need to access request parameters in the View whether it be for creating a URL. This should be regarded as a data source as well. Does this mean that we have to code up View Helper to access this also? (This isn’t a smart ass rhetorical question either – I really want to know what do you do?)To handle cases where I need to display parameters in the view, I assign the view parameters in the controller something along the lines of:
$this->view->username = $this->_getParam(‘username’);
- Say you need to display session data in the view, how would you go about doing that? Personally, as with the request parameters, I assign the session data to the view in the controller:
$this->view->somesessiondata = $session->somedata;
- Now say we need to get some data from the model… no problem! I can use the getModel view helper that makes me feel so smart. To do this though, we need to set up the view so that it has the ID parameter.
$data = $this->getModel(‘SomeModel’)->findById($this->id);
// or if we us a view helper for parameters (I said IF – not entirely sure about this yet)
$data = $this->getModel(‘SomeModel’)->findById($this->getParam(‘id’));
Now compare this with providing the data that the view needs via the Controller.
// in the controller
$this->view->data = $this->_service->findById($this->_getParam(‘id’));
$this->view->username = $this->_getParam(‘username’);
$session = new Zend_Session_NameSpace
$this->view->sessionData = $session->sessionData;// in the view
<h2>User Details</h2>
<?php foreach ($data as $key=>$val) : ?>
<?=$key?>: <?=$val;?>
<?php endforeach; ?><p>You have requested the username: <?=$this->username; ?> which is not available. </p>
Also at one point I was thinking why we are fighting so hard to decouple the view from the controller anyway? They are coupled from the file system and have default conventions like indexAction is coupled with index.phtml view script in an index script directory (which matches controller name).
Having said that though, I don’t see a strong case for or against pushing or pulling models to or from the View. Maybe I’m just missing the point somewhere. In any case, I’d be grateful to know (and learn from) what your take is on this subject matter.
So to sum it up, these are the questions that are floating through my head at the moment.
- What are the _specific_ advantages of having the View pull data from the model directly?
- What are the _specific_ disadvantages of having the Controller push data from the model into view member variables?
- Is the example I specified above (creating view helpers, registry, action helpers) overkill just to achieve something that may or may not be a design problem?
Well, i think that both methods are valid and helps to make code simpler.
I usually define view variables through controller $view property and I’m confortable with this. Simple, objective and it works (K.I.S.S).
And, if access models in Views is the “problem”, why not try the following:
//DummyController::dummyAction()
// Using AutoLoad
$categoriesModel = new Categories();
// Define View now have acces to the model
$this->view->categoriesModel = $categoriesModel;
// dummy-action.phtml
$allCats = $this->categoriesModel->getAll();
And, if AutoLoad was implemented well, i think that we won’t need action/view helpers to get their instances.
The question is: *when* we’ll use Views *without* controllers, to make them access their Models independently?
For me, the “model” layer is solely responsibility of the Application, even when the subject is access to/from models by other objects. Every model has his own rules.
Thank you for chiming in. I’m grateful for your feedback.
I am of the same opinion. Something I forgot to mention this in the post.
Making it so that the View can pull it’s own Models complicates things sacrificing simplicity.
Now if there are advantages in giving the view the ability to pull data on it’s own (I honestly, at this point in time cannot think of any), then we can at least weigh up the advantages against the complexity it brings with it.
I’ve been thinking that passing only model objects to views, and never native scalars/arrays, would be the way to go.
Remember that in PHP every object is a reference. So you’re not pushing anything, and the view and the controller have references to the same object.
Using objects instead of native types allows you to do lots of OO stuff, like making a model implement ArrayAccess.
What would be cute is for a model to allow injection of a view helper, and then call its view helper in its __toString() magic method. So rendering a model looks very simple in the view: . The magic would take care of the rest!
Hi Bill,
Thanks for the feedback and presenting your take on the subject.
So you’re saying that you don’t see anything wrong with passing the entire Model to the view?
I’ve leaned a little this way, but was deterred as the model has methods that read and write from and to the data source.
I guess this simplifies things a little more because now the view has a reference to the model object and that it’s up to the developer to not abuse the fact that the write methods are available to the view…
> What would be cute is for a model to allow
> injection of a view helper, and then call its
> view helper in its __toString() magic
> method. So rendering a model looks very
> simple in the view: . The magic would take
> care of the rest!
Not sure I got you on this one – If I understand you correctly, you’re saying that the model should have a __toString() method that provides functionality for a viewHelper/renderer to be set.
So in essence, you’re inverting the ViewHelper process – rather than passing the model to the ViewHelper, you’re passing the ViewHelper to the Model… right?
// in controller
public function indexAction()
{
$this->view->model = $this->_service;
}
// in view script.
< ?php $this->model->setViewHelper('SomeVIewHelper'); ?>
< ?php echo $this->model; ?>
But couldn’t you just do something like the following?
< ?php echo $this->SomeViewHelper($this->model); ?>
Though, I may have missed something…
“Passing the entire model” is no big deal because it’s just a reference to an object.
Yes, the view should be restricted to read-only usage of the model. If you’re worried that view developers won’t be able to restrain themselves, then create a proxy to wrap the model, so the view has no access to anything but read-only methods.
Regarding the view helper, you could either set it in the view, or in the controller, or there the framework could infer a view helper by a naming convention, else your model class definition could declare its own preferred view helper class.
But yes, my idea is that you could use <?= $this->model ?> and it would render the model using the right view helper.
BTW, I think your model service factory stuff is over-engineered. Just instantiate a model in the controller, and assign that object to be a member of the view. Keep it simple, and use less plumbing.
I thought about the restraint/”rules of engagement” side of things, but I try to lean toward semantics – I like the idea about applying a read only proxy.
> [...] But yes, my idea is that you could
> use < ?= $this->model ?> and it
> would render the model using the
> right view helper.
Sounds interesting. I might actually investigate it when I have time to play around with new concepts.
> BTW, I think your model service
> factory stuff is over-engineered.
> Just instantiate a model in the
> controller, and assign that object to
> be a member of the view. Keep it
> simple, and use less plumbing.
I thought exactly that when I was using it, I’ve made the shift a few months ago and this is sort of the point I’m trying to make with this post by asking the question.
The factory used a registry which basically made sure that there is only ever one instance of the model being used for models which is accessed by the controller and the view.
That is indeed a lot of plumbing.
One more thought: the “model service factory” is getting dangerously close to the “factory factory factory” in *Why I Hate Frameworks*:
http://discuss.joelonsoftware.com/default.asp?joel.3.219431.12
lol “So this week, we’re introducing a general-purpose tool-building factory factory factory, so that all of your different tool factory factories can be produced by a single, unified factory.”
That sounded like me when I had first learnt about the Factory Design Pattern.
This might be going over the edge a bit but perhaps Bill’s idea could be construed as a “Strategy” pattern in terms of how something is represented as a string depending on the context. For example, if I’m in a view script I’d want __toString() to return a valid (x)html fragment, if i’m doing xml-rpc i’d want xml, if i’m doing json-rpc or ajax i’d want json, etc. In some way this might be an extension of the relationship between __sleep() and serialize()/unserialize().
Maybe this is just a purely academic idea though … not sure if this would offer any *real* productivity gains at the cost of some complexity. The main issue would seem to be where and how to select the context. Probably in a boostrap script or something.
Plus this might complicate issues where one has to work with a designer in the case of html.
David, wouldn’t that be the Visitor pattern? I’m not well-read enough on all my patterns.
Two ways this can go.. but are interesting. One, instead of injecting the model you decorator the model with a class that knows about displaying itself. This way in the view, like you say its much simpler. Also easier then to reuse your model in terms of its view. By decorating you keep adding decorators, to slightly change the display. The other side of this is that by adding a model to your view you have to open up your open with a bunch of getters/setters which usually breaks Encapsulation. The approach for this would be some of DTO object you can pass from the model layer to the view. This way you do not have to expose your model, and you still have an object.
I’m a bit new to the whole MVC concept myself. Never really used anything like it before, as I only had a view/code setup with smarty before I started experimenting with ZF in 2009 Jan.
)
Because of that my only source of how things ’should’ look like, is from php/zf point of view (at least thats how I interpretted what I’ve read up till now
To me the view scrits are meant to be as simple as possible; I’m always trying to keep it as clean of unnecessary code as possible. (I actually struggle when I feel I’m calling something from a view script when there should be a cleaner method of achieving the same goal.)
If I do it like that I can work on the important stuff in the controller, while leaving the more trivial stuff, lik layout and styling to my biorobot co-workers who ar enot as deep in ZF yet as I am.
For this approach passing the variables that are needed from the controller to the view seems somewhat better to me, than exposing the whole object in the view script.
This is something I’ve came across just today, and I feel like its related to your problem, so I’m curious about your opinion:
I’m building a site with I18 support, the layout, views, forms, etc. are all localized.
As I’m using the Translator Bootstrap resource(at this point its undocumented on the ZF site, but its been available for a while, like some other resources /layout for example/), I’ve set up the translator with some nice and clean code.
application.ini:
…
resources.translate.data = APPLICATION_PATH “/translations”
resources.translate.adapter = “Array”
resources.translate.options.scan = “filename”
…
and in the Bootstrap.php:
…
protected function _initTranslator() {
$this->bootstrap(array(‘layout’,'view’));
$translate = $this->bootstrap(‘translate’)->getResource(‘translate’);
$layout = $this->getResource(‘layout’);
$view = $this->getResource(‘view’);
$layout->translate = $translate;
$view->translate = $translate;
return $translate;
}
…
So this way I can access the translator in the layout script and the view scripts as $this->translate and localization works out of the box.
Also the Translator bootstrap resource registers the translator in the Zend_Registry as the Zend_Translate key, so whatever i18 aware component you use in your code it also works.
The only thing that didn’t work like that was a special form, where I use the viewscript form decorator, and it doesn’t inherit things from the view, so the translator is unavailable in that code segment. Its also one of the “not that well documented” parts of ZF. (The element view script decorator has some documentation, but the form version lacks it…I’ve spent a few hours with trial by error method, also browsing through the ZF library code, about what is available for use with it.)
In that particulare script I start the code with:
and then ofc it works.
My problem is that somehow this feels bad…I don’t know why, but I feel uneasy asif I’m doing it wrong. Fetching something from the global registry in a view script.
What do you think?
Okay, seems like there was some stripping in the post so this part was lost in /dev/null
In that particular script I start the code with:
…
$translate = Zend_Registry::get(‘Zend_Translate’);
…
and then ofc it works.
Hi,
I’ve found that you need model access from your view if you have two-layer caching (model-level and view-level) which is needed if you use the same model for your WS’s and web pages with very complex view logic. The rendering itself takes a time long enough to cache it, but you also need to cache the data on it’s own.
I think there’s a few strands to the debate over View Helpers.
The first one is to be careful of an absolutist approach. Most of us are guilty of presenting one way of accompishing a task to the exclusion of all else, not always because because we believe it’s the One-True-Way, but because it suits the example we provide. This leads to the fallacy that a View Helper *must* as opposed to *may* look after its own models. In reality, if doing it from a controller is simpler (KISS) without sacrificing both testing capability (testability) and reusability, then there’s not much wrong with it. This is most evident in in-out models – where a View needs a specific Model, but does not itself have much information on WHICH model. Then you have a choice of a) pass the ID, or b) pass the Model itself from a controller. Which is simpler?
The second is what constitutes a model. Like Bill, I’d argue the model provided to a View should be the actual object itself. It costs little (compared to converting to yet another value, not a reference, like an array), offers greater flexibility and the advantage of Model provided methods to the View, and splits the Model View between the View hosted model and its View Helper hosted formatting helpers.
The third, and the one where View Helpers and Models are most likely to be completely warranted, are when the Model is independent of the immediate purpose of the request. This is most obvious in layouts, where the main content is purpose of the request (so its models may come direct from the controller) but it is surrounded by other pieces of markup derived from other models not related to that request. Consider a a blog displaying entries which might also present a summary of comments. The comments are not the purpose of the request (that’s the entries), so the comments are most likely to be derived from a View Helper directly querying a Model it knows about itself. More relevantly, these additional models tend to need nothing (or very little) from the controller.
The key to View Helpers and Models is whether it passes a specific rule, and the rule is simple. Controllers are not Page Controllers. They handle the request at hand, but nothing else if possible. The everything else that’s possible will sit in the View and/or Model leaving the controller thinner, lighter and specific. If its specific nature makes it easier to pass a specific Model to the View directly, well, why fight KISS?
Padraic!
Thank you for chiming in on this subject matter.
Thank you for your feedback which adds to Bill’s recommendation of passing the model object to the view rather than passing the data returned by the model to the view.
This feedback is basically what I was after. Getting responses from those who have more experience than I do on this and confirming certain directions I’m trying to explore.
I feel like you are again are there standing with a flag at the Checkpoint showing me which direction to go as you have been at Zend Nabble forums several months ago giving guidance on why models should not extend Zend_Db_Table.
“why fight KISS?” affirms a few ideas and directions I’ve been thinking of heading at this point in time.
Thanks again. I am eternally grateful!
I agree that one should not feel limited by one way to do it.
Designing the Model is equivalent to doing the OO design for all your application business logic. I don’t think there’s a legitimate one-size-fits-all solution.
In “Facts and Fallacies of Software Engineering” Robert L. Glass says,
“Eighty percent of software work is intellectual. A fair amount of it is creative. Little of it is clerical.”
I assert that any framework helps with the part of coding that is clerical. A framework is meant to simplify the repetitive work that really does have common implementation in all apps.
This doesn’t work for the Model, because it’s too hard to make a generalization about what a Model does. Trying to make a general-use framework for Models either sacrifices flexibility that you need, or else results in a framework that retains flexibility, but has usage that is complex that it gives no benefit compared to writing the app directly.
Thank you to everyone who has chimed in with their comments and opinions especially to Bill and Padraic. You guys have confirmed, for me anyway, that it is perfectly fine to pass the model object to the view from the controller.
I am very happy with the feedback and have confirmed a bunch of theories I’ve been throwing around in my mind for some time now.
Thank you!