Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Given the concept of 'skinny controllers, fat models' and the general acceptance that Views can directly call on Models when requiring data for output, should one consider handling the 'get and display' parts of requests within the Views and not the Controller? For example (attempted to keep code fairly generic):

Controller

<?php

class Invoice extends Base_Controller {

    /**
     * Get all the invoices for this month
     */

    public function current_month() {

        // as there's no user input let's keep the controller very skinny,
        // DON'T get data from the Model here, just load the view

        $this->load->view('invoice/current_month');

    }

}

View

<?php

// directly retrieve current month invoices here

$invoices = $this->invoice_model->get_current_month();

// get some other display-only data, e.g. a list of users for a separate list somewhere on the page

$users = $this->user_model->get_users();

?>

<h1>This month's invoices</h1>

<ul>
<?php foreach ($invoices as $invoice) { ?>

<li><?php echo $invoice['ref']; ?></li>

<?php } ?>
</ul>

To me, this makes at least some sense in the cases where a request is essentially just a View. Why should the Controller have to collect and pass on the data to the View when it can just retrieve it itself? This leaves the Controller open for purely 'Application level' processing (e.g. handling GET/POST requests, managing access rights and permissions etc.) as well as keeping the Models reusable and all the other good stuff.

If this example was extended to allow a user to filter the results, the Controller would just handle the POST from the form and pass the filters to the View, which would then request the data again, this time with the filters.

Is this a valid approach to developing an MVC application? Or am I overlooking an important part of the role a Controller should play?

share|improve this question

4 Answers 4

up vote 13 down vote accepted

Yes, it can technically be done. No, it shouldn't be done. And yes, you're missing a bit of what the controller is there for.

The controller is there to decouple the View from the Model. The decoupling is beneficial because you should look at the View as almost throw-away code. As your UI technology changes, you want to minimize the rework required in generating a new View. The controller enables that decoupling and provides a place for your code that will live through UI technologies.

It works in reverse as well if you need to add to or change out your Model. All of the upstream changes will be contained within the Controller and your Views will be left alone.

The other risk is that while the View is very simple now, you have less guarantee that it will remain so simple throughout its life. By calling the Model directly from the (very simple) View, you've opened the door a bit to allow additional bad practice to creep in later when the very simple View needs to become not-so-very simple. A future developer will be tempted to make more Model calls from the not-so-very simple View instead of refactoring the code and interacting with a Controller.

share|improve this answer
1  
Great answer, thank you. Extending your 'looking ahead' scenario slightly; if there is common information on a page that is separate to what is requested (e.g. user is viewing a specific product, a general list of 'latest special offers' are shown at the side) how/where should the call to the offers_model->get_latest() be made? Adding this into every method in the controller (as I've foolishly attempted before) seems like overkill and distinctly un-DRY. –  Adam Westbrook Jan 31 '13 at 19:02
2  
@AdamWestbrook Take a look at MVVM. The ViewModel part of that can address this specific problem. You can add the offers_model->get_latest() to a ProductViewModel base class or something similar. –  Zachary Yates Jan 31 '13 at 19:05
1  
Great, I'll definitely look into MVVM, thanks again. –  Adam Westbrook Jan 31 '13 at 19:14
    
Very good answer, will defiantly keep this starred. Personally I'm also a big fan of MVVM :) –  Benjamin Gruenbaum Jan 31 '13 at 21:44
    
@BenjaminGruenbaum Are you using MVVM in PHP? If so are you using a particular framework for it? –  Adam Westbrook Feb 1 '13 at 10:42

Given the concept of 'skinny controllers, fat models' and the general acceptance that Views can directly call on Models when requiring data for output

No. This is not correct. View can not directly call on Models. Views should not have access to Model objects, unless for some reason the programmer has exposed those objects to the View.

should one consider handling the 'get and display' parts of requests within the Views and not the Controller?

That basically erases the Controller, and defeats the point of having them.

Why should the Controller have to collect and pass on the data to the View when it can just retrieve it itself?

The Controller doesn't collect the data. The Model does the collecting of the data. The Controller decides if this data should be passed to the view. The View just does the presentation of the data.

If this example was extended to allow a user to filter the results, the Controller would just handle the POST from the form and pass the filters to the View, which would then request the data again, this time with the filters.

No.

The Controller checks if the POSTed data is valid, it then passes this data as options to the Model, which would then query the datasource and return the data, and the Controller passes that to the View.

Is this a valid approach to developing an MVC application? Or am I overlooking an important part of the role a Controller should play?

The Controller operates as a handler to requests by the browser. A dispatcher sends the request to a controller's action, which in turn, spreads the request out to the Models. The Models contain all the business logic (this is the fat part), and give the data back to the controller. The controller can then simplify and adjust the data so that it's easier for the View to present it.

The point of the View is to decouple the structure and dependency between the presentation of HTML and the DataSource. While this can be difficult. Views don't always present data that came directly from a Model. The controller often adds extra data that is relevant.

I'm sure there are a lot of tutorials out there on MVC. I'd recommend reading some of them.

share|improve this answer
    
Thanks Mathew. For clarification, up until now I've always decoupled the View and Model with the Controller as read and suggested. However, since starting to read up on keeping 'skinny' Controllers I've just been wondering what should/could be moved out of them, seems the thought process that lead me to this question was a step or two too far! –  Adam Westbrook Jan 31 '13 at 19:06
    
When you start to get Models used by many controllers. The need for them to be fat becomes very clear. When the View starts to contain a lot of PHP then you know your controller is to thin. When your controllers are very fat. It's difficult to get other controllers to operate the same way (for example, adding an API service). –  Mathew Foscarini Jan 31 '13 at 19:18

I found your question very interesting because I ran into the same issue while learning Python recently.

While the answers given make a convincing argument, I thought I would add another opinion I came across in which the View does get the Model's state without going through the Controller.

MVC

It is important to note that both the view and the controller depend on the model. However, the model depends on neither the view nor the controller. This is one the key benefits of the separation. This separation allows the model to be built and tested independent of the visual presentation. The separation between view and controller is secondary in many rich-client applications, and, in fact, many user interface frameworks implement the roles as one object. In Web applications, on the other hand, the separation between view (the browser) and controller (the server-side components handling the HTTP request) is very well defined.

Model-View-Controller is a fundamental design pattern for the separation of user interface logic from business logic. Unfortunately, the popularity of the pattern has resulted in a number of faulty descriptions. In particular, the term "controller" has been used to mean different things in different contexts. Fortunately, the advent of Web applications has helped resolve some of the ambiguity because the separation between the view and the controller is so apparent.

In Application Programming in Smalltalk-80: How to use Model-View-Controller (MVC) [Burbeck92], Steve Burbeck describes two variations of MVC: a passive model and an active model.

The passive model is employed when one controller manipulates the model exclusively. The controller modifies the model and then informs the view that the model has changed and should be refreshed (see Figure 2). The model in this scenario is completely independent of the view and the controller, which means that there is no means for the model to report changes in its state. The HTTP protocol is an example of this. There is no simple way in the browser to get asynchronous updates from the server. The browser displays the view and responds to user input, but it does not detect changes in the data on the server. Only when the user explicitly requests a refresh is the server interrogated for changes.

MVC - Passive Model

I'm not in a position to say which of the opinions is "right", and to be honest, I am a bit more confused after reading the answers here and the linked article.

Full text of article here.

share|improve this answer
    
Right, and the other thing that adds confusion is client-server, which the original SmallTalk MVC did not really account for. In client-server (e.g. with javascript) there are presentation-oriented models, views, and controllers on the client, and domain-oriented views and controllers on the server, though the server also does some presentation-oriented processing adding confusion. Also, sometimes we want a domain views to have some persistence, which means the view parameters form their own model, that is not necessarily part of the domain model. –  Erik Eidt Feb 2 '13 at 17:54
    
Thank you for the link, I knew I wasn't mad in thinking this! This is essentially what I'd been going off before I took the idea a bit too far, as long as the Model isn't dependant on anything what does it matter how/where it is accessed? I haven't decided what approach I'm going to take on my next development yet, but this definitely helps. –  Adam Westbrook Feb 4 '13 at 12:06

Another thing to consider is that you appear to have autoloaded the user_model and invoice_model to allow the the view to access them. For this to work reliably, you probably autoload all of your models (because $this->load->model() just looks wrong in a view, doesn't it...)

Doing this unnecessarily bloats your stack by loading a bunch of stuff that may never get used. Part of the reason for having multiple models is to allow you to encapsulate related logic and load only what you need for a given task.

This looks like CodeIgniter. I've done a lot of CI development and I can share from personal experience that you really don't want to autoload more than you really have to. Try adding $this->output->enable_profiler(TRUE); in a controller's constructor and fiddle with autoloads (including helpers like database): you'll likely see a significant change in load and execution times, but especially in memory allocation.

share|improve this answer
1  
Good points, you're right this is based on CI, though I removed some of the specific syntax for clarity. I've got into the habit of 'autoloading' pretty much everything for largely time and DRY reasons, seemed a bit mad to have a lot of the same load->model in most controllers and methods. Not using a proper autoload function is one of the things I most dislike about CI's backwards compatibility, but that's a whole other discussion... –  Adam Westbrook Feb 1 '13 at 10:40

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.