Magento 2 Development Workshop Learn More

Magento 2 for Beginners

10 lessons

Passing Data From Controller to Template

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 the static text.

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

This might be enough for a static website, but not for Magento 2 website. In this lesson, we are going to 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 dynamic content can be rendered 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 in order to follow the lesson.

Controller Logic

Let's have a closer look at the execute() method of the View Controller class.

The Controller/Page/View.php file:

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

As you can see, the resultFactory is used to create a new instance of a Magento\Framework\View\Result\Page class. The Page class includes logic, which is used to render all blocks and templates on the page. The created instance of the Page class includes the path to the example.phtml template from the MageMastery_FirstLayout module.

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

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

First of all, let's assign a result of the create() method into the $page variable.

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

Now, we can access any Block class, that has been added in the page for further rendering. The Page class has a dependency on a Layout class that can be used to retrieve an instance of a block by calling the getBlock() method. The getBlock(string $name) method accepts the $name argument.

In the previous lesson we've 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 $block variable is now refer to a Template class instance.

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

The Template class allows us to set additional data. For this, the setData() method has to be used. There are other methods available for setting data to a Template object, but for this lesson, we will only use the setData() method. The Template::setData(string $name, mixed $value = null) method accepts two arguments. First argument is the name of the key for which the value has to be set. 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 assigned and it can be accessed 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:

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;
}

The execute() method creates an instance of the Page class, returns an instance 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 block. Lastly, the Page object is returned from the execute() method for rendering.

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 that is rendered by the Magento\Framework\View\Element\Template class has access to a $block variable inside the template. The $block variable is an instance of a current Template class or any subclass, that extends the Template class.

In order to get access to the custom_parameter inside 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 should be located in a so-called Service Layer or a PHP class that represents such business logic. We are going to 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 is not the only way to pass data from a PHP class to a PHTML template. This is only one of the ways that you should be aware of when building custom Magento 2 functionality. The preferred method of passing data to a PHTML template is a usage of a View Model class. The View Model class and its capabilities is the next lesson of the Magento 2 for Beginners course.