Magento 2: Simple Hello World Module – Step-by-Step Beginner Tutorial

This beginner step-by-step tutorial shows how you can create a simple and basic HelloWorld module / extension in Magento 2. The necessary files are listed with the code.

This module just calls a block function in template file to print Hello World text.

GitHub Repository of the Module: https://github.com/chapagain/simple-helloworld-magento2

Things to note:

In Magento 2, there is no code pool. So, no more confusion with app/code/local, app/code/core, and app/code/community. Your module will simply be in the directory app/code/YourNamespace/YourModule.

Also, everything related to your module will be inside your module directory (app/code/YourNamespace/YourModule). So, there is no more separate design folder (app/design/frontend/default/default/template) for templates or layouts, or no more separate folder for module configuration xml (app/etc/modules).

Here are the folders that can be in your module directory (app/code/YourNamespace/YourModule):

Block: contains PHP view classes
Controller: contains PHP controller classes
etc: contains configuration files; like modules.xml, routes.xml
Model: contains PHP model classes
Setup: contains classes for module database structure and data setup which are invoked when installing or upgrading.
Api: contains any PHP classes exposed to the API.
i18n: contains localization files.
Plugin: contains any needed plug-ins.
view: contains view files, including static view files, design templates, email templates, and layout files.

For more detail: Magento 2 module file structure

Here is the step-by-step guide on creating Magento 2 module/extension.

I have set the module’s namespace as Chapagain and module’s name as HelloWorld. So, our module is Chapagain_HelloWorld.

1) Create Module’s Configuration File

app/code/Chapagain/HelloWorld/etc/module.xml


<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">

    <module name="Chapagain_HelloWorld" setup_version="2.0.0" />

</config>

2) Create Module’s Frontend Router File

app/code/Chapagain/HelloWorld/etc/frontend/routes.xml


<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="helloworld" frontName="helloworld">
            <module name="Chapagain_HelloWorld" />
        </route>
    </router>
</config>

Note: frontName="helloworld" in the above code. This indicates that helloworld is used in the URL to access our module.

3) Create Controller Class

In Magento 2, we should create a separate controller class for each action. Each controller class will only have one method named execute().

So,

for indexAction() of IndexController, we will create app/code/Chapagain/HelloWorld/Controller/Index/Index.php

for viewAction() of IndexController, we will create app/code/Chapagain/HelloWorld/Controller/Index/View.php

Here, we will create a controller class for indexAction for our module.

app/code/Chapagain/HelloWorld/Controller/Index/Index.php


<?php
namespace Chapagain\HelloWorld\Controller\Index;

class Index extends \Magento\Framework\App\Action\Action
{
        /**
         * @var \Magento\Framework\View\Result\PageFactory
         */
        protected $resultPageFactory;

        /**
         * @param \Magento\Framework\App\Action\Context $context
         * @param \Magento\Framework\View\Result\PageFactory resultPageFactory
         */
        public function __construct(
            \Magento\Framework\App\Action\Context $context,
            \Magento\Framework\View\Result\PageFactory $resultPageFactory
        )
        {
            $this->resultPageFactory = $resultPageFactory;
            parent::__construct($context);
        }
    /**
     * Default customer account page
     *
     * @return void
     */
    public function execute()
    {
        return $this->resultPageFactory->create();
    }
}
?>

Here, the execute() method does the work of loadLayout() and renderLayout() in Magento 1.x.

4) Create Block Class

Here, I have written the constructor but haven’t used it much. We will be using the constructor a lot in Magento 2 for dependency injection purpose. But for now, let’s only focus on the getHelloWorld() function which returns Hello World text.

app/code/Chapagain/HelloWorld/Block/HelloWorld.php


<?php
namespace Chapagain\HelloWorld\Block;
class HelloWorld extends \Magento\Framework\View\Element\Template
{       
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,       
        array $data = []
    )
    {       
        parent::__construct($context, $data);
    }
    
    public function getHelloWorld()
    {
        return 'Hello World';
    }
    
}
?>

5) Create Design Layout File

app/code/Chapagain/HelloWorld/view/frontend/layout/helloworld_index_index.xml


<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <title>
            Simple Magento 2 Module
        </title>
    </head>
    <body>
        <referenceContainer name="content">
            <block class="Chapagain\HelloWorld\Block\HelloWorld" name="helloworld" template="Chapagain_HelloWorld::helloworld.phtml" />
            <!--<block class="Magento\Framework\View\Element\Template" template="Chapagain_HelloWorld::helloworld.phtml"/>-->            
        </referenceContainer>
    </body>
</page>

As you can see above, helloworld.phtml template file is called for the block class HelloWorld. The title of the page is defined as Simple Magento 2 Module. We have also defined our page layout as 1column.

6) Create Design Template File

In the template file, we can write custom HTML tags and also call the block function.

Here, we will call the getHelloWorld() function of our block class.

app/code/Chapagain/HelloWorld/view/frontend/templates/helloworld.phtml


<h2>
    <?php echo $block->getHelloWorld(); ?>
</h2>

Note that, in Magento 2, we call the block object as $block.

7) Register your Module

You have to register your module in your Magento 2. This is done through Magento ComponentRegistrar class. You should create a new file named registration.php in your module’s directory.

app/code/Chapagain/HelloWorld/registration.php


<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Chapagain_HelloWorld',
    __DIR__
);
?>

8) Create composer file

app/code/Chapagain/HelloWorld/composer.json


{
    "name": "chapagain/helloworld",
    "description": "Simple Hello World Module for Magento 2",
    "type": "magento2-module",
    "license": [
        "OSL-3.0",
        "AFL-3.0"
    ],
    "authors": [
        {
            "email": "your.email@example.com",
            "name": "Mukesh Chapagain"
        }
    ],
    "minimum-stability": "dev",
    "require": {},
    "autoload": {
        "files": [
            "registration.php"
        ],
        "psr-4": {
            "Chapagain\\HelloWorld\\": ""
        }
    }
}

9) Activate the Module

Finally, you have to activate your module. There are two ways to do so.

a) Editing app/etc/config.php

Open app/etc/config.php add a key/value (YourNamespace_YourModule => 1) in the array of that file.


<?php
return array (
  'modules' => 
  array (
    'Chapagain_HelloWorld' => 1, // we add this key => value
    'Magento_Store' => 1,
    'Magento_AdvancedPricingImportExport' => 1,
    'Magento_Directory' => 1,
    'Magento_Theme' => 1,
    ...
    ...
    ),
);  

b) Through command in terminal

  • Open terminal
  • Go to your Magento 2 root folder
  • Enable the module

php bin/magento module:enable Chapagain_HelloWorld
  • Then, run the following command:

php bin/magento setup:upgrade

If it doesn’t work, then you can try using sudo at the beginning of the command.


sudo php bin/magento setup:upgrade

This will automatically add our module entry in the app/etc/config.php file.

10) Clean/Flush Cache

Don’t forget to flush Magento 2 cache.

You can manually delete all files and folders inside the following directories:

var/cache/ (magento cache)
var/page_cache/ (full page cache)
var/generation/ (compiled code)

Or, you can delete them through command line:


rm -rf var/cache/* var/page_cache/* var/generation/*

Or, the best way to clean or flush cache is to use Magento command in terminal:

You can either use cache:clean</strong> OR <strong>cache:flush.

cache:clean = Deletes all items from enabled Magento cache types only. Disabled cache types are not cleaned.
cache:flush = Purges the cache storage. All cache types are flushed/deleted.


php bin/magento cache:clean
php bin/magento cache:flush

If it doesn’t work, then you can try using sudo at the beginning of the command.


sudo php bin/magento cache:clean
sudo php bin/magento cache:flush

To check the enabled/disabled status of all cache types, you can run the following command:


php bin/magento cache:status

All done. Now, our Magento 2 ‘HelloWorld‘ module should have been installed. We can browse it in the URL.

http://example.com/helloworld/index/index/

Or, simply http://example.com/helloworld/

When you browse the above URL, you should get something like this in the browser:

magento simple helloworld module

GitHub Repository of the Module: https://github.com/chapagain/simple-helloworld-magento2

Hope this helps. Thanks.