How to Create a Template Block in Magento 2

by Mark Shust · August 20, 2015

Hopefully you've already read Setting Up Your Magento 2 Module the Right Way with Composer & Packagist, so we can start creating our module. We won't use Composer or Packagist in this tutorial to save some time, as we are just writing code to test out functionality. Let's get right into things.

Create module skeleton

First, we'll create a our module skeleton:

mkdir -p app/code/Foo/Bar/etc

Next, we'll create the module definition file at app/code/Foo/Bar/etc/module.xml:

<?xml version="1.0"?>
<config xmlns:xsi="" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
    <module name="Foo_Bar" setup_version="0.0.0"/>

With Magento 2, modules are not automatically picked up until they are enabled by command line. So let's enable the module. The setup:upgrade line is needed right now because of a bug in Magento 2, but this should only be needed in the future if there are database installer scripts in your module.

./bin/magento module:enable Foo_Bar
./bin/magento setup:upgrade

Note that if you are running Magento through a Docker container, you should "bash" into the container first before executing shell commands:
docker exec -it CONTAINER_ID bash

And with that, we're off to the races, as enabling a module also flushes the cache for us.

Block class and Layout XML

Magento 2 is now aware of our module, so let's create our block class. We'll do this by extending the \Magento\Framework\View\Element\Template class, and create a custom getName function:

namespace Foo\Bar\Block;

* Baz block
class Baz
    extends \Magento\Framework\View\Element\Template
    public function getTitle()
        return "Foo Bar Baz";

Note the changes from Magento 1; specifically setting a custom namespace and the new format for extending a block template, along with the new class.

Now that we have programmed our block, we want to display it on the home page. The naming of the file is important as this is the new way of using layout handles. The cms_index_index.xml name will make our block only appear on the home page (module_controller_action.xml).

Create our folder location:

mkdir -p app/code/Foo/Bar/view/frontend/layout

Then create a layout XML file at app/code/Foo/Bar/view/frontend/layout/cms_index_index.xml containing:

<?xml version="1.0"?>
<page xmlns:xsi="" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
        <referenceContainer name="main">
            <block class="FooBarBlockBaz" template="default/baz.phtml"/>

The referenceContainer element is referencing the layout container for our block. To read more about layout containers, please visit the official documentation on layouts. We also recommend reading thoroughly through the XML instructions for layouts to get a deeper understanding of the changes to the layout layer of Magento 2.

Explore the core base container and block layout definitions by checking out the layout and page_layout folders in app/code/Magento/Theme/view/frontend.

Template HTML and Caching

Next we'll create our folders for the template:

mkdir -p app/code/Foo/Bar/view/frontend/templates/default

Then the actual template HTML at app/code/Foo/Bar/view/frontend/templates/default/baz.phtml containing:

 * Baz view template
 * @var $block FooBarBlockBaz
<h1><?php echo $block->getTitle(); ?></h1>

If you need to flush the cache for any reason (if the block isn't showing or was previously cached), you can do so with one of the following command lines depending on what cache you want to clear. Any changes to the layout XML will always require a cache flush with the layout param, while the new full page cache will need to be flushed on most PHP code changes.

./bin/magento cache:flush --all # Flush all cache types
./bin/magento cache:flush layout  # Flush Layout XML
./bin/magento cache:flush full_page  # Flush Full Page Cache


And with a cache flush, refresh your home page and you should see Foo Bar Baz shown at the top of the main content area!

We've created a GitHub repository with this sample module code, which will also be updated in the future with other code samples.

This post authored by
Mark Shust
Read more about Mark

Mark Shust is the lead eCommerce Developer for Mage Inferno, a development firm specializing in Magento 2 modules. He has over 10 years of web development experience in the eCommerce, real estate, business-to-business, and information technology industries. Mark has specific expertise in database engineering and management, development processes, and client frontend development, and has taken projects through the development lifecycle from conceptualization through completion. Mark is a Zend Certified Engineer, a Magento Certified Developer Plus, and has a wide knowledge range of LAMP server management and Linux-based programming. He has in-depth experience creating custom extensions, building out vendor-specific customizations, and performance enhancements & improvements for both Magento Community and Enterprise platforms.