How do I create a simple “Hello World” module in Magento 2?

Magento 2 is a well-engineered framework for building e-commerce websites. It is based on the PHP programming language and MySQL/MariaDB (relational) database. All functionality in Magento 2 is built based on the Oriented Programming approach.

Every feature in Magento 2 is located in a module. A module is a package that contains all necessary files and logic that helps a feature be “alive” in Magento 2. The vendor/magento/module-cms is one of the examples of a Magento 2 module.

Creating a Module

A module is located in the app/code/ directory and includes the vendor folder name. Inside the vendor name, the Magento 2 module is created. Let’s create a new Magento 2 module with the vendor name “MageMastery” and the module/feature name “HelloWorld”.

cd app/code/
mkdir -p MageMastery/HelloWorld

Let’s create 2 mandatory files inside the HelloWorld module so that Magento 2 can register it in the system.

The registration.php file:

<?php

use Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(
    ComponentRegistrar::MODULE,
    'MageMastery_HelloWorld',
    __DIR__
);

The ComponentRegistrar::register() call registers a new module with the name MageMastery_HelloWorld inside the current directory using the __DIR__ PHP constant.

The module.xml file is located inside the etc directory of the HelloWorld module.

mkdir etc
touch etc/module.xml

Let’s add the routing configuration to the module.xml file:

<?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="MageMastery_HelloWorld" />
</config>

The <module /> XML node provides the name of the Magento 2 module. The name is then going to be used by the Magento 2 application. For instance, you can see the module name when using the bin/magento module:enable CLI command.

Registering a Module

Magento 2 provides a Magento CLI script for operations related to setting up an application, registering new modules, clearing caches, reindexing a catalog of products, etc. The Magento CLI script is located inside the bin directory and can be accessed by running it via the command line.

bin/magento

Let’s enable the module by running the following command:

bin/magento module:enable MageMastery_HelloWorld

After that, the module has to be installed and registered in a Magento 2 application. Here is the second command, that should be executed:

bin/magento setup:upgrade

Setting up Module’s Routing

The module we’ve created does nothing, except show itself via Magento CLI. The next step in the Hello World tutorial is to register the module’s routing configuration. It will allow us to create a controller and view it on a storefront.

First, let’s create a new routes.xml file.

mkdir -p etc/frontend
touch etc/frontend/routes.xml

The configuration of the routes.xml file:

<?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="magemastery_helloworld" frontName="helloworld">
            <module name="MageMastery_HelloWorld" />
        </route>
    </router>
</config>

With the above configuration, we register a new module’s front name “helloworld”. The front name can be used to access controller classes.

If we access the https://magento.test/helloworld URL, we can see the 404 Page Not Found page. It is time to create an Index controller that is responsible for handling and rendering content when we try to access the above URL again.

Let’s create the Index controller class. First, we have to create the Controller/Index directory.

mkdir -p Controller/Index
touch Controller/Index/Index.php

The Index controller class:

<?php declare(strict_types=1);

namespace MageMastery\HelloWorld\Controller\Index;

use Magento\Framework\App\Action\HttpGetActionInterface;

class Index implements HttpGetActionInterface
{
    public function execute()
    {
        // TODO: Implement execute() method.
    }
}

After refreshing the https://magento.test/helloworld URL in a browser, we can see the below result:

1 exception(s):
Exception #0 (InvalidArgumentException): Invalid return type

The execute() method has to return an instance of the Magento\Framework\Controller\ResultInterface interface. Let’s update the implementation of the execute() method as below:

public function execute(): ResultInterface
{
    /** @var Raw $result */
    $result = $this->resultFactory->create(ResultFactory::TYPE_RAW);
    $result->setContents('Hello World');
    return $result;
}

The full implementation of the Index controller:

<?php declare(strict_types=1);

namespace MageMastery\HelloWorld\Controller\Index;

use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\Controller\Result\Raw;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Controller\ResultInterface;

class Index implements HttpGetActionInterface
{
    public function __construct(
        private readonly ResultFactory $resultFactory
    ) {
    }

    public function execute(): ResultInterface
    {
        /** @var Raw $result */
        $result = $this->resultFactory->create(ResultFactory::TYPE_RAW);
        $result->setContents('Hello World');
        return $result;
    }
}

The result after refreshing the https://magento.test/helloworld URL.

The same result can be viewed if we navigate to the https://magento.test/helloworld/index/index URL or even https://magento.test/helloworld/index URL. It happens because the default controller directory name is Index and the controller class is… drum roll – Index.php. The routing resolves both default names and we can access the Index controller without explicitly specifying the controller name and directory.

It is also possible to have a different directory name inside the “Controller” directory, as well as the name of a controller class. For example, the helloworld/product/add route matches the MageMastery\HelloWorld\Controller\Product\Add controller.

What’s Next

We learned the very basics of Magento 2 development and created our first Magento 2 module. The module consists of the registration files, routing configuration, and controller that renders the “Hello World” text on a storefront.

It is recommended to learn how to create layout and template files, going forward. It will help to get an idea of the alternative response objects, that are created in controllers. We will also render the Hello World as part of a fully functional Magento 2 website, wrapped with the header, and footer.

Similar Posts

Leave a Reply