Implement a View Model in a layout block

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)l

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.

Complete and Continue  
Extra lesson content locked
Enroll to access all lessons, source code & comments.
Enroll now to Unlock