Passing Data From Controller to Template

From the Template and Layout Rendering lesson, we've learned how to create a new template and render it on a custom page with the help of a layout. As you've noticed, the template provides HTML markup with static text.

<h1>My First Template</h1>
<p>With Layout support</p>

This code might be enough for a static website, but not for Magento 2. In this lesson, we will learn how to pass data from the PHP side, specifically from an Action Controller to the template.

By the end of this lesson, you will know one of the ways how to render dynamic content on a page.

Lesson Overview

In this lesson, we are going to learn the following:

  • How to pass data from a controller class to a template?
  • How to get access to a block class from a controller?
  • How to assign data to a block class?
  • How to render dynamic data in a template?

Before we begin

You will need to download the source code from the previous lesson to follow the class.

Controller Logic

Let's look closely at the execute()method of the View Controller class.

The Controller/Page/View.phpfile:

public function execute()
{
    return $this->resultFactory->create(ResultFactory::TYPE_PAGE);
}

As you can see, the resultFactory is for creating a new instance of a Magento\Framework\View\Result\Pageclass. The Page class includes logic for rendering all blocks and templates on the page. The created instance of the Page class consists of the path to the example.phtml template from the MageMastery_FirstLayoutmodule.

Once the execute()method returns a Page object, it will trigger the Page::render()method, rendering content on a page.

However, if we want to pass content from a Controller class into the example.phtml template, modify the logic of the execute()method.

First, let's assign a result of the create()method to the $pagevariable.

public function execute()
{
    /** @var Page $page */
    $page = $this->resultFactory->create(ResultFactory::TYPE_PAGE);
    return $page;
}

Now, we can access any Block class for further rendering. The Page class depends on a Layoutclass for retrieving an instance of a block by calling the getBlock()method. The getBlock(string $name)method accepts the $nameargument.

In the previous lesson, we discussed that the name of the Block declaration added to the magemastery_firstlayout_page_view.xml layout file is magemastery.first.layout.example. We can retrieve an instance of a block by calling the getBlock()method and passing the block name.

<block class="Magento\Framework\View\Element\Template"
       name="magemastery.first.layout.example"
       template="MageMastery_FirstLayout::example.phtml" />

The $blockvariable now refers to a Template class instance.

$block = $page->getLayout()->getBlock('magemastery.first.layout.example');

The Template class allows us to set additional data. For this, use the setData()method. Other methods are available for setting data to a Template object, but we will only use the setData()method for this lesson. The Template::setData(string $name, mixed $value = null)method accepts two arguments. The first argument is the name of the key for which we set the value. Furthermore, the key has to be used to access the assigned value.

Let's assign a value to the key called custom_parameter.

$block->setData('custom_parameter', 'Data from the Controller');

As a result, the block instance has new data and is assessed via the getData()method.

$data = $block->getData();
print_r($data);
/* Retult
Array ( 
    [type] => Magento\Framework\View\Element\Template 
    [custom_parameter] => Data from the Controller 
)
*/

Alternatively, we can pass the name of the key to the getData(string $key = null, int $index = null)method.

$customParameter = $block->getData('custom_parameter');
echo $customParameter;
// Result: Data from the Controller

The result of the modified execute()method:

{
    /** @var Page $page */
    $page = $this->resultFactory->create(ResultFactory::TYPE_PAGE);
    /** @var Template $block */
    $block = $page->getLayout()->getBlock('magemastery.first.layout.example');
    $block->setData('custom_parameter', 'Data from the Controller');
    return $page;
}

The execute()method creates an instance of the Page class and returns a sample of a Template from the pool of declared blocks that has the magemastery.first.layout.example block name. Then the custom value is assigned to the league. The Page object is returned from the execute() rendering method.

The app/code/MageMastery/FirstLayout/Controller/Page/View.php file:

<?php

declare(strict_types=1);

namespace MageMastery\FirstLayout\Controller\Page;

use Magento\Framework\App\Action\Action;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\View\Element\Template;
use Magento\Framework\View\Result\Page;

class View extends Action
{
    public function execute()
    {
        /** @var Page $page */
        $page = $this->resultFactory->create(ResultFactory::TYPE_PAGE);
        /** @var Template $block */
        $block = $page->getLayout()->getBlock('magemastery.first.layout.example');
        $block->setData('custom_parameter', 'Data from the Controller');
        return $page;
    }
}

Template Logic

Every PHTML template rendered by the Magento\Framework\View\Element\Template class has access to a $blockvariable inside the template. The $blockvariable is an instance of a current Template class or any subclass that extends the Template class.

To get access to the custom_parameterinside the example.phtml template, we have to use the Template::getData()method.

<p><?= $block->getData('custom_parameter'); ?></p>

It is also practical to add a doc-block with the name of the class, so the IDE, in my case PHPStorm, will highlight all public methods. The final example.phtml template:

<?php
use Magento\Framework\View\Element\Template;
/** @var Template $block */
?>
<h1>My First Template</h1>
<p>With Layout support</p>
<p><?= $block->getData('custom_parameter'); ?></p>

As a result, the page should render the custom parameter.

Custom Parameter Rendered on a Page

Important to Know

Even if you can use PHP inside a PHTML template, there shouldn't be any business or calculation logic located in the template. All business logic is in a so-called Service Layer or a PHP class that represents such business logic. We will talk more about the Service Layer in the upcoming lessons. PHTML templates should be as simple and tiny as possible and only include data and simple PHP logic inside, such as loops and conditions.

Other Methods for Passing Dynamic Data

This way is not the only to pass data from a PHP class to a PHTML template; this is only one of the ways you should be aware of when building custom Magento 2 functionality. The preferred method of passing data to a PHTML template is using a View Model class. The View Model class and its capabilities are the following Magento 2 for Beginners course lesson. 

Join it and share it with friends and colleagues!