Back to Top

Magento 2 Development 08: Layout and Templates

Updated 6 March 2024

Now let’s come back to frontend development. Earlier we created a controller where I wrote a “Hello World” statement to show you that the controller is working. But in Magento, we don’t write HTML code in the controller.

To show HTML content we use .phtml files in Magento. These .phtml files are called template files.

To map the controller with .phtml files we use layout files. The layout files are of .xml type. As all of these are related to viewing the page. So it makes sense to put them in a different folder, which is called the view folder.

First, we need to modify the controller file, Controller/Manage/Add.php

File Structure

Updated code for Controller/Manage/Add.php file

Searching for an experienced
Magento 2 Company ?
Find out More
namespace Webkul\BlogManager\Controller\Manage;

use Magento\Customer\Controller\AbstractAccount;
use Magento\Framework\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;

class Add extends AbstractAccount
     * @var PageFactory
    private $resultPageFactory;

     * Dependency Initilization
     * @param Context $context
     * @param PageFactory $resultPageFactory
    public function __construct(
        Context $context,
	PageFactory $resultPageFactory
    ) {
	$this->resultPageFactory = $resultPageFactory;

     * Provides content
     * @return \Magento\Framework\View\Result\Page
    public function execute()
        $resultPage = $this->resultPageFactory->create();
        $resultPage->getConfig()->getTitle()->set(__('Add Blog'));
        $layout = $resultPage->getLayout();
        return $resultPage;

Here we are using \Magento\Framework\View\Result\PageFactory class to initialize the layout. With this we can configure the page, here we have set the Title of the page. And after calling the getLayout() method to process the layout file, we returned the result page.


Now if you notice we have not explicitly mentioned the layout file name in the controller. So Magento will look for the layout file with the name routerId_controllerName_actionName.xml. If we want then we can explicitly give like,


For the layout file, we need to create a view/frontend/layout folder under the module directory. In the layout folder, we need to create a layout file with the name blogmanager_manage_add.xml. If you remembered we used blogmanager as our router id. It’s common practice to use routerId as the same as frontName because then the layout file name will be similar to the URL.

Folder Structure

Code for view/frontend/layout/blogmanager_manage_add.xml file

<?xml version="1.0"?>
<page xmlns:xsi="" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
        <referenceContainer name="content">
            <block class="Magento\Framework\View\Element\Template" name="" template="Webkul_BlogManager::add.phtml" />

The body node refers to that we are modifying contents within the body tag of the HTML. The page layout in Magento is made out of multiple containers. And the container can have nested containers. The innermost containers have blocks in them and each block can have child blocks.

Layout Types

As you can see in the page tag we have used the layout attribute with the value 1column. Magento supports different types of layouts such as,
i) 1coumn
ii) 2columns-left
iii) 2columns-right
iv) 3columns

For simplicity, you can think of the header, footer, and main content as individual containers. However, Magento’s layout structure is much more complex, which helps us to modify any component. For the 2columns-left layout, the main content will have two sub-containers, one for content and another on the left side as a sidebar container.

With the referenceContainer tag, we can target any container, here we are targeting the main container whose name is content. You can find more container and block names in the vendor/magento/module-theme/view/frontend/layout/default.xml file.


Inside the container, we are calling our phtml file with a block tag. Here we are using the default template block class Magento\Framework\View\Element\Template but we can create our own block class if we have to pass some data into the phtml. We will see more about the Block class in the next blog. The block tag has a name attribute, we can use any sensible name here to identify that block.


The interesting part in the block tag is template=”Webkul_BlogManager::add.phtml”, this represents the path of the template file. The first part of :: is the module name and the second part is the path in reference to the view/frontend/templates folder. As in the path we have given the phtml file name so we can directly create add.phtml file under the view/frontend/templates folder.

Folder Structure

Code for view/frontend/templates/add.phtml file

<div class="blog-container">
    <form class="blog-form">
        Title: <input type="text" name="title"/>
        Content: <textarea name="content"></textarea>
        <button type="submit">Submit</button>

After writing all of this code we have to run the di compile command. And now if you browse the URL you will see the page,


Please try out different layout types on your own.

If you make some changes in the template file and can not find it when reloading the page then please flush the cache.

php bin/magento cache:flush


We are aiming to create a blog portal where customers can write blogs. So it makes much more sense that the page should appear like other customer account pages and instead of manually entering the URL we should have a menu in the customer navigation.

To add the customer navigation menu we will follow the “Magento2 – Add New Link in My Account Navigation Panel” blog. We have to create a customer_account.xml file under the view/frontend/layout folder. Magento already has this XML file we are just appending our code to it.

Folder Structure

Code for view/frontend/layout/customer_account.xml file

<?xml version="1.0"?>
<page xmlns:xsi="" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
        <referenceBlock name="customer_account_navigation">
            <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-blog-add" after="-" >
                    <argument name="label" xsi:type="string" translate="true">Add Blog</argument>
                    <argument name="path" xsi:type="string">blog/manage/add</argument>

Now let’s modify our already created blogmanager_manage_add.xml file to match the customer account page structure.

Updated code for view/frontend/layout/blogmanager_manage_add.xml file

<?xml version="1.0"?>
<page xmlns:xsi="" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="customer_account"/>
        <referenceContainer name="content">
            <block class="Magento\Framework\View\Element\Template" name="" template="Webkul_BlogManager::add.phtml" />

Here you can see that we have removed the layout type and added the <update handle=”customer_account”/> tag. Basically, it says that copies everything from the customer_account.xml, so it will copy all the structure from customer_account.xml which acts as a base for every customer account-related page.

Now when we di compile and reload we will see something like,


Folder structure till now,

Folder Structure

PS. Please run the di compile command if you create a new file, modify any .xml file, or make changes in the constructor of a class. Sometimes running di compile might not have any effect then we should explicitly remove the generated/code folder by running rm -rf generated/code from the Magento root directory. Please be careful while running the rm -rf command.

Next Blog -> Magento 2 Development 09: Form Validation and Saving Data

Previous Blog -> Magento 2 Development 07: Model, Resource Model and Collection

. . .

Leave a Comment

Your email address will not be published. Required fields are marked*

Be the first to comment.

Back to Top

Message Sent!

If you have more details or questions, you can reply to the received confirmation email.

Back to Home