This article is part of a series on design patterns for framework independent code, especially to write extensions for Magento 1 and Magento 2 alike.
All Parts:
- Introduction: Write Extensions For Magento 1 And Magento 2
- Part 1: Accessing Configuration Data
- Part 2: Using Dependency Injection
- Part 3: Building Bridges
- Part 4: Preparing Data For Output
- Part 5: Using Advanced Autoloading
- Part 6: Leveraging PSR Interfaces
- Part 7: Iterating Iterators
Every application has its own means to render a HTML page. There are template engines with include mechanisms, HMVC, and of course the XML based two step view of Magento with its layout and blocks. Somehow we need to use them if we want to display anything in our extension.
Can we abstract it? Possibly. Is it worth the effort? I’d argue “no”. MVP (Model View Presenter) comes to mind, as it was used in GWT (Google Web Toolkit), but this was a framework that tried to disguise web applications as desktop applications and I don’t want to go down that road again.
However, the exact presentation is not part of the business logic that we want to have decoupled. But what we can – and should – do, is to extract everything from templates, block classes and the like that is not dealing with presentation details.
View Models
In fact I want them to only receive the data they need and avoid giving them access to anything that can cause side effects. You don’t save models from within a template, right?
For this purpose, I introduced View Models. I took the term from the Model View ViewModel pattern (MVVM) which splits the classic “view” into “view” (renders) and “view model” (contains UI logic and data). However, I am not going to implement this pattern. It makes sense in desktop applications or in JavaScript based web applications (Angular.js and Knockout.js use it), but not for web backend, i.e. PHP. As Anthony Ferrara stated recently, and I wholeheartedly agree:
Here’s my “beginners guide to MVC for the web”:
Lesson 1
You don’t need “MVC”.
— Anthony Ferrara on “MVC on the web”
Read the whole post if you don’t know it yet, and also the second part that talks about MVC’s “siblings”.
So what do my View Models actually do? In the simplest form, they are just data objects. For example, I have a CategorySuggestion class that presents a suggested category based on what you typed (in the autosuggest preview):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
final class CategorySuggestion { private $title; private $numResults; private $url; /** * @param string $title * @param int $numResults * @param string $url */ public function __construct($title, $numResults, $url) { $this->title = $title; $this->numResults = $numResults; $this->url = $url; } /** * @return string */ public function getTitle() { return $this->title; } /** * @return int */ public function getNumResults() { return $this->numResults; } /** * @return string */ public function getUrl() { return $this->url; } } |
The block receives this instead of a Category instance, because
- it does not care about other aspects of the category
- the “num_results” (results for a given search term within the category) is semantically not part of the Category itself, but here we need it
Can you tell that I am not a friend of using arrays as structs? This is again has something to do with explicitness in code.
You could say that view models do not represent data as it is stored, but data as it needs to be displayed. Some of my view models even contain a $cssClasses property, though this would probably be better refactored into something more semantical.
Responsibility of my View Models:
- hold data that needs to be displayed
- allow querying this data for output related properties
What they are not responsible for:
- rendering output (no HTML!)
- operate on the business layer (they should not trigger database queries themselves, only contain their results)
This is similar to what block classes are supposed to do in Magento, but with stricter boundaries. In Magento, blocks pull the information they need from models; in my architecture, the business layer pushes this information to them in form of view models. More on that later on.
View Helpers
Something else that you can probably extract into the library are “view helpers”. I know, “helper” does not mean much, and I’ve said it myself:
In general, having classes named Helper, Util or similar just says “I have some functions that I don’t know where to put” and don’t make much sense as a class.
But you probably know the term for methods that are used to modify output data and I’ve been guilty to use it myself more often than not.
For example, in the Solr extension, the autosuggest blocks had a method named highlight()
which added <span class="highlight">
around the search term in results.
I extracted this functionality into a HtmlStringHighlighter class which implements this simple interface:
1 2 3 4 5 6 7 8 9 |
interface StringHighlighter { /** * @param string $haystack * @param string $needle * @return string */ public function highlight($haystack, $needle); } |
The blocks that need it now can retrieve or instantiate this default highlighter but are still free to replace the concrete implementation. Putting the HTML with highlight added into the View Model would have robbed us of this flexibility. Remember, the view model is not responsible for rendering output.
Push instead of Pull
As stated above, I prefer to push data to the presentation layer instead of it being pulled. The old version of our Solr extension did it the Magento way and requested search results from the block classes. Of course, the resulting collection and other data was saved to properties to prevent requesting them twice, and there certainly is an advantage on this kind of lazy loading: You only load data if you really display it. So if the filter block has been removed from the layout, we don’t aggregate the filter data.
But there is also a great disadvantage: you don’t have full control over the order of operations, i.e. what happens when.
This already has been a source of bugs. I was once faced with a case where results were loaded before all filters were applied, since the filter block was loaded after the pagination block. The pagination block triggered loading the results, but the filter block applied the filters.
So how do we turn this around? Here is a simplified example for a Magento 1 controller:
1 2 3 4 5 6 7 8 9 10 11 |
$this->loadLayout() $listBlock = $this->getLayout()->getBlock(self::LAYOUT_BLOCK_LIST); $filterBlock = $this->getLayout()->getBlock(self::LAYOUT_BLOCK_FILTER); $searchResult = Mage::helper('integernet_solr/factory') ->getSolrRequest(Factory::REQUEST_MODE_SEARCH) ->doRequest(); $listBlock->setSearchResult($searchResult); if ($filterBlock) { $filterBlock->setSearchResult($searchResult); } $this->renderLayout(); |
We load the layout first to instantiate all the blocks (which also initializes the layered navigation in this case), then make a search request and pass the results to the block(s) that renders it, then actually start rendering the page.
Another option, especially if the blocks need different data, is to pass them to the library as well. The blocks could implement this interface, provided by the library:
1 2 3 4 |
interface SearchResultView { public function setSearchResult(SearchResult $result); } |
The SolrRequest in our library could then get another method:
1 |
public function addView(SearchResultView $view = null) |
And the code from above would be changed to:
1 2 3 4 5 6 7 8 9 |
$this->loadLayout() $listBlock = $this->getLayout()->getBlock(self::LAYOUT_BLOCK_LIST); $filterBlock = $this->getLayout()->getBlock(self::LAYOUT_BLOCK_FILTER); Mage::helper('integernet_solr/factory') ->getSolrRequest(Factory::REQUEST_MODE_SEARCH) ->addView($listBlock) ->addView($filterBlock) ->doRequest(); $this->renderLayout(); |
Now pushing the data to the view is also the responsibility of the independent library, we just need to pass it to the views.
The next article will address a problem that mainly occurs in Magento 1 which follows some outdated standards: Using Advanced Autoloading

Author: Fabian Schmengler
Fabian Schmengler is Magento developer and trainer at integer_net. His focus lies in backend development, conceptual design and test automation.
Fabian was repeatedly selected as a Magento Master in 2017 and 2018 based on his engagements, active participation on StackExchange and contributions to the Magento 2 core.
Hi!
This has been a very interesting read so far.
I wonder how can you apply this approach to blocks not linked to controllers.
For instance a module adds a widget in a column displaying some information pulled from DB. The block would be added by layout.xml but there is no way of injecting dependencies via constructor.
How do you go about injecting the repository models for instance? Would you use a factory helper in the constructor? Wouldn’t that break testability?
Thanks for your feedback and the very good questions! I’ll have to think about that particular use case, it did not occur to me yet.
But since in Magento 1 you cannot easily inject dependencies in blocks via constructor, I usually resort to some kind of singleton as entry point for the library. For better testability this can look similar to:
Yes I’ve been doing something like what you propose lately, but I also like the Idea of separating “rendering blocks” from “logic blocks”.
I think I’ll start using some sort of “wrapper blocks” that would behave like “entry points” (kinda like a controller of sorts) which will then _toHtml the child “rendering blocks”.
Something like (sorry I don’t know how to highlight syntax here)