Türchen 7: Better Blocks: Magento 2 PHP View Models


Magento 2 Blocks

Since the very beginning of Magento 1, all server side view layer logic was encapsulated in Block classes. This approach has not changed in Magento 2 (so far).

Last week I had the chance to talk to Anton Kril of Magento and he told me I should consider switching to a new way of providing view layer logic instead of using blocks: PHP View Models.

About blocks

I believe we all probably agree that templates should only be about representation, and should not contain business logic.
The view level business logic is what blocks are for. At least for me, the most common type of logic in blocks is to provide data to the template.

Block classes have to extend from \Magento\Framework\View\Element\AbstractBlock, which in turn implements \Magento\Framework\View\Element\BlockInterface.
Since most custom blocks require rendering a template, in most cases they actually inherit from \Magento\Framework\View\Element\Template, one step further up the inheritance chain.

Problems with blocks

While blocks do their job just fine, they do have some shortcomings:

All blocks use constructor injection, so when a custom block requires additional dependencies, it has to pass the transient Context dependency along to the parent::__construct() method.

Naturally, many developers then access the parents dependencies through protected getters or even protected fields.
This interweaving of custom logic and platform code leads down the path of complexity.
Code becomes harder to understand and maintain when compared to plain classes without inheritance.

Also, when using tests to drive the development of blocks, it is quite cumbersome having to deal with the parent class dependencies, even though they actually are not related to custom business logic.
This is an additional obstacle to developers starting out on the TDD journey and facilitates the myth that testing is hard.

PHP view models

While writing this post I just discovered the following PHPDoc comment above the template block class:

This comment was added in the 2.2 release and describes exactly what Anton was referring to.

Even better, since Magento 2.2.1 we don’t even have to specify the class argument on the <block/> node, since class="Magento\Framework\View\Element\Template" is the default anyway.

I now declare most of my blocks in layout XML like this:

The templates begin like this:

The view models have to implement a marker interface, or we end up with an exception:

This is the ArgumentInterface this exception refers to:

This restriction is a security precaution. Since layout can be configured from multiple places – including the adminhtml by the merchant – it serves to limit the number of blocks that can be instantiated by layout instructions.

Having to implement this interface is not a real inconvenience in practice. I enjoy working with almost decoupled view models more than blocks extending from AbstractBlock.

A constructor does not need to call parent::__construct(), and any dependencies are plain to see.

There still are use some cases where using a custom block is required. Choosing the template to render conditionally for example. But in most cases view models are good enough.

Benefits of view models

In a nutshell, using view models instead of blocks provides a better separation of custom and platform code, which leads to code with the following properties:

  • easier to understand
  • more maintainable
  • more reusable
  • more upgrade safe
  • simpler to test

Happy Christmas and happy coding!


  • 8. December 2017

    Thank you Vinai, exactly what I was looking for while working on my latest Magento 2 Module.

  • 25. May 2018

    getting NULL for $viewModel = $block->getViewModel(); can you help me?

    • 4. October 2018


      if it is the method defined in your “ViewModel”file(In the above code it is Example.php) then please add below code in the template:
      getData(‘viewModel’) ;
      echo $viewModel->getViewModel();

  • 21. June 2018

    Thanks for sharing!

  • Sheshagiri
    2. September 2018

    Very Useful!! Thanks

  • 24. January 2019

    In my opinion, the topic of the view-models pattern is very close to the behavior pattern theme.
    For example, how the behavior in the Yii2 Framework:

    How do you think about this?

  • 18. May 2019

    Thanks for sharing! The XML and Template files in the post are messed up 🙂

  • 9. November 2019

    Thanks for sharing!!

Leave a Reply to Alex Cancel reply

Your email address will not be published. Required fields are marked *