A free and open-source book on ZF3 for beginners


4.23. Skinny Controllers, Fat Models, Simple Views

When developing a website using Model-View-Controller pattern, there is a risk of misunderstanding the role of controllers, views and models. This results in making the controllers huge and models small, which in turn makes it difficult to test and support your application. This section's goal is to give you a general understanding of what code may be placed in a controller class, what code may be placed in a view template, and what code may be placed in a model class.

4.23.1. Skinny Controllers

The idea behind the term "skinny controller" is that typically, in your controller classes, you put only the code that:

A controller class should avoid:

For an example of a "skinny" controller, look at the CurrencyConverterController class below. This controller provides the "convert" action method whose goal is to convert an amount of money from EUR to USD currency. The user passes the amount of money through the "amount" GET variable.

class CurrencyConverterController extends AbstractActionController 
{  
    // Currency converter model
    private $currencyConverter;

    // Constructor. It's purpose is to "inject" dependencies.
    public function __construct($currencyConverter)
    {
        $this->currencyConverter = $currencyConverter;
    }

    // The "convert" action displays the converted money amount
    public function convertAction() 
    {  
        // Get the money amount from GET
        $amount = (float)$this->params()->fromQuery('amount', -1);
    
        // Validate input data
        if($amount<0) {
            // Money amount is missing
            $this->getResponse()->setStatusCode(404);
            return;
        }
 
        // Pass the data to the CurrencyConverter model
        $convertedAmount = $this->currencyConverter->convertEURtoUSD($amount);	
		
        return new ViewModel([
            'amount'=>$amount,
            'convertedAmount'=>$convertedAmount
        ]);
    }
}

The controller's action method above does the following:

4.23.2. Fat Models

Because you need to keep your controllers as thin as possible, most of the business logic of your application should be put into model classes. In a properly designed Model-View-Controller application, models look "huge". A model class may contain the code which:

In a model class you are not recommended to:

If you follow these principles, you will encounter that your models are easy to test, because they have clearly identified input and output. You can write a unit test which passes some test data to input end of the model, retrieves the output data and verifies that the data is correct.

If you are confused whether to put certain code in a controller or in a model, ask yourself: is this an important business logic that needs to be carefully tested? If the answer is yes, you should put the code in a model.

4.23.3. Simple View Templates

Because most of the logic is stored in models, your view templates should be as simple as possible to produce the presentation of the data passed through the variable container. In a view template, you may:

The view template is not recommended to:

If you follow these principles, you will encounter that your views can easily be substituted without modifying the business logic of your application. For example, you can easily change the design of your web pages, or even introduce changeable themes.


Top