Implement a View Model in a layout block
Want to learn everything about M2?
Quickly learn and reference all Magento programming basics, concepts & patterns, even with no prior experience.
We just learned about the purpose and use of View Models in Magento's MVVmC architecture. Now, we're going to put that knowledge into practice and integrate a View Model into a block of the Magento layout.
Create the View Model
We will start by creating a View Model for our Macademy_Jumpstart
module. Let’s say we want to display a welcome message to our customers based on the time of day, which would be some advanced logic that would make our template more complex than it should be. Because of this, the logic to determine the message to be displayed will be stored in our View Model.
First, create a ViewModel
directory within the root of our module:
app/code/Macademy/Jumpstart/ViewModel/
Create a WelcomeMessage.php
file in the ViewModel
directory with this content:
<?php declare(strict_types=1); namespace Macademy\\Jumpstart\\ViewModel; use Magento\\Framework\\View\\Element\\Block\\ArgumentInterface; class WelcomeMessage implements ArgumentInterface { public function getWelcomeMessage(): Phrase { $hour = date('G'); if ($hour < 12) { return __('Good morning!'); } elseif ($hour < 17) { return __('Good afternoon!'); } else { return __('Good night!'); } } }
We explicitly implement the ArgumentInterface
as it's required by Magento to allow our class to be used as an argument in layout XML files. The getWelcomeMessage()
method contains the logic determining the welcome message based on current time.
Add the View Model to layout block
Since Magento avoids using PHP logic within the template files, the View Model won't be automatically available in our template. We should declare it in our layout XML block to pass it to the template.
Change the block node in jumpstart_index_index.xml
:
<?xml version="1.0"?> <page xmlns:xsi="<http://www.w3.org/2001/XMLSchema-instance>" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="content"> <block name="macademy_jumpstart_welcome" template="Macademy_Jumpstart::welcome.phtml"> <arguments> <argument name="welcome_message_view_model" xsi:type="object">Macademy\\Jumpstart\\ViewModel\\WelcomeMessage</argument> </arguments> </block> </referenceContainer> </body> </page>
Here, we added the arguments
node and passed our View Model as an argument to the block. The name
attribute will be used in our template file to retrieve the data, which is welcome_message_view_model
. We won’t name it just view_model
as there could be multiple view models assigned for each block.
Retrieve data in the template
Open welcome.phtml
template file we created before, and modify the content to retrieve the welcome message:
<?php /** @var \\Macademy\\Jumpstart\\ViewModel\\WelcomeMessage $viewModel */ $welcomeMessageViewModel = $block->getData('welcome_message_view_model'); ?> <h1><?= $welcomeMessageViewModel->getWelcomeMessage() ?></h1>
You're now calling the getWelcomeMessage()
method of our View Model inside the welcome.phtml
template file.
After updating and flushing Magento's cache using the bin/magento cache:flush
command, Magento will now display an appropriate welcome message on your store's frontend depending on the current time of day.
You've successfully separated the logic from the view. This organizes complex logic away from the view, making template files simpler and only concerned with code related to the presentation of data.