Layout and Blocks in Magento 2.x

In this blog post, we will see how to add layout file and block to your module

In the previous blog, we created an ManishJoy_HelloWorld module. Using the same module, we will display “Hello World” again but this time using layout/block with a proper page structure.

Now, let’s start with the steps:

Step 1: Controller

In the previous World.php controller file, we had simply displayed “Hello World” on an empty page without any CSS/Stylying getting applied to it. We will remove that and use the layout system of Magento.

The new code for World.php controller would be:

<?php
namespace ManishJoy\HelloWorld\Controller\Hello;
 
use Magento\Framework\App\Action\HttpGetActionInterface;
 
class World extends \Magento\Framework\App\Action\Action  implements HttpGetActionInterface
{    
    protected $resultPageFactory;

    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory
    )
    {
        $this->resultPageFactory = $resultPageFactory;       
        return parent::__construct($context);
    }
     
    public function execute()
    {
        return $this->resultPageFactory->create(); 
    } 
}

Here we have injected ‘PageFactory’ into the controller’s constructor and which is used further to initialize the layout in execute().

Dependency Injection, is one of the major changes in Magento 2 and will discuss it in detail later. For now, just use this code directly.

Step 2: Layout

Now we will setup the layout file for our action.

In Magento 2 all layout files of a module are located at “view/frontend/layout” folder of a module and for each route we need to create a different layout file. In our case the file would be:

ManishJoy/HelloWorld/view/frontend/layout/manishjoy_hello_world.xml

The content of this file would be:

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">       
    <referenceContainer name="content">
        <block
            template="ManishJoy_HelloWorld::content.phtml"
            class="ManishJoy\HelloWorld\Block\Main"
            name="manishjoy_layout_test"/>
    </referenceContainer>
</page>

Magento 2 also supports a layout file named default.xml, which gets loaded for all of the actions of any module/action.

Step 3: Block

In the previous step, we defined our layout with a keyword “class”, which is our block class. Now, let’s create this class at this path: ManishJoy/HelloWorld/Block/Main.php

The code for this file would be:

<?php
namespace ManishJoy\HelloWorld\Block;
  
class Main extends \Magento\Framework\View\Element\Template
{   
    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context
    )
    {
        parent::__construct($context);
    }
    
    protected function _prepareLayout()
    {
    }
}

This is a simple and empty block with no functions as we are just doing the basic operations here.

Step 4: Template

Now that our block file is set, next we need to set the template file.

Templates for a module are located in “view/frontend/templates” directory so we need to create the file at this path optionally

ManishJoy/HelloWorld/“view/frontend/templates/content.phtml

Let’s now add “Hello World” to this page:

<h1><?php echo __('Hello World'); ?></h1>

Now you are all set, now you can open the URL http://yourbaseurl.com/manishjoy/hello/world to test it.

You will see “Hello World” again but with full page layout (header, footer etc.)

Note: __() is the i18n (multiple language/localization) function for magento2. We should always use this and never directly display a string.

Step 5: Passing data from Block to Template

In step 3, we created a very basic block and in step 4, we simply had displayed a static string “Hello World”. But in real world, we need to fetch data etc. and show it in the template. But, We cannot create functions in template files to do such operations. Now let’s see how can we pass data from Block to template (phtml) files.

<?php
namespace ManishJoy\HelloWorld\Block;
  
class Main extends \Magento\Framework\View\Element\Template
{   
    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context
    )
    {
        parent::__construct($context);
    }

    protected function _prepareLayout()
    {
        $this->setText('Hello World');
    }
}

As you can see we have used this $this->setText('Hello World'); to send data from block.

Now in the template file, you need to update the code like this to fetch this data and display:

<?php echo $block->getText(); ?>

Updated: