Magento2 – Layout/Blocks – Magento Development Series Part 2

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

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

Step1

In the previous World.php action file, we had simply displayed ‘Hello World’. We will remove that and use magento’s layout system.
The new code for World.php action would be

<?php
namespace Excellence\Hello\Controller\Hello;


class World extends \Magento\Framework\App\Action\Action
{
    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 magento2 and will discuss it in detail later. For now, just use this code directly

Layout

Now we will setup the layout file for our action.
In magento2 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

Excellence/Hello/view/frontend/layout/excellence_hello_world.xml

and content 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="content.phtml"
            class="Excellence\Hello\Block\Main"
            name="excellence_test"/>
    </referenceContainer>
</page>

more details on how to use layout, template and block, check the theme development series.

magento2 also supports a default.xml layout file, which gets loaded for all action’s of that module

Blocks

Now that we have setup the layout file, next we need to setup block file. As defined in our layout, our block file will be located at

Excellence\Hello\Block\Main

folder.

The contents for block file are

<?php
namespace Excellence\Hello\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, empty block with no functions.

Template

Now that our block file is set, next we need to set the template file.
Templates for a module a located in “view/frontend/templates” folder so we need to create the file

Excellence/Hello/view/frontend/templates/content.phtml

We will add the code

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

Now when you open the url /excellence/hello/world you will see “hello world” again but with full page layout (header, footer,etc)

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

Template/Block Passing Data

Passing data from block to template, is used very frequently.
It is very simple to do. Update to block code to

<?php
namespace Excellence\Hello\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('Testing');
    }
}

As you can see we have done

$this->setText()

in our block file.

To access in this in our template file we need to

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

There is a big different in how its done in magento1. In magento1 we use ($this) variable in template files, but in magento2 we are using $block

Proper Usage of Block/Template

Block file should contain all the view logic required, it should not contain any kind of html or css. Block file are supposed to have all application view logic.

The template files on the other hand should mainly contain all html scripting. It should contain as little view logic as possible. This is a very important practice to follow.

  • sohan

    getting error Recoverable Error: Argument 2 passed to ExcellenceHelloControllerHelloWorld::__construct()

    • Hi sohan,

      Following code will work :

      namespace ExcellenceHelloControllerHello;

      class World extends MagentoFrameworkAppActionAction
      {
      protected $resultPageFactory;
      public function __construct(
      MagentoFrameworkAppActionContext $context,
      MagentoFrameworkViewResultPageFactory $resultPageFactory)
      {
      $this->resultPageFactory = $resultPageFactory;
      parent::__construct($context);
      }

      public function execute()
      {
      return $this->resultPageFactory->create();
      }
      }

      After replacing this code clear var/generation and var/cache.

      Cheers 🙂

  • swamy

    How to add child blocks in magento2

    • Manish Prakash

      You can use $this->addChild function to add a child block. for example:

      $this->addChild(
      ‘back_button’,
      ‘MagentoBackendBlockWidgetButton’,
      [‘label’ => __(‘Back’), ‘template’ => ‘Vendor_Moduel::template.phtml’ ‘class’ => ‘cancel’]
      );

      Then it is necessary to use $this->getChildHtml(‘back_button’) in parent block template to render child block with the template. It’s better to utilize layout to define templates and blocks.

  • eLARAKI

    At the blocks part, do you create the file at:
    ExcellenceHelloBlockMainMain.php
    or is it:
    ExcellenceHelloBlockMain.php
    ??
    Great tutorial btw!

    • Priyansh Agrawal

      it is ExcellenceHelloBlockMain.php