How to create a basic module in Magento 2

We’re going to build a very simple module in Magento 2. When finished, the module’s output will say “Hello world!” in the block content on a custom frontend route.

Prerequisites

Needless to say, you will need the latest Magento 2 version which is currently 2.1. If you need any help with the Magento 2 installation we have a great article regarding this particular topic “How to install Magento 2”.

Before we start a Magento 2 module development, there are two things people often forget and we recommend you to do:

1. Disable Magento cache

Disabling Magento cache during development will save you some time because you won’t need to manually flush the cache every time you make changes to your code.

The easiest way to disable cache is to go to Admin → System → Cache Management → select all cache types and disable them.

2. Put Magento into a developer mode

You should put Magento into a developer mode to ensure that you see all the errors Magento is throwing at you.

In order to do this, open your terminal and go to the Magento 2 root. From there you should run the following command:

php bin/magento deploy:mode:set developer

Creating the module files and folders

Module setup

If you have used the Magento 1 version, you’re used to the term code pools – community, core and local folders which reside in the app/code folder. In Magento 2, there are no more code pools. Modules are grouped by namespace and placed directly in the app/code folder.

So our first step is to create the module folder and necessary files required to register a Magento module.

1. Create the following folders:

  • app/code/Inchoo
  • app/code/Inchoo/Helloworld

The Inchoo folder is the module’s namespace, and Helloworld is the module’s name.

Note: If you don’t have the code folder in your app directory, create it manually.

2. Now that we have a module folder, we need to create a module.xml file in the app/code/Inchoo/Helloworld/etc folder with the following code:

<?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="Inchoo_Helloworld" setup_version="1.0.0">
    </module>
</config>

3. To register the module, create a registration.php file in the app/code/Inchoo/Helloworld folder with the following code:

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

4. Open your terminal and go to the Magento 2 root. Run from there the following command:

php bin/magento setup:upgrade

If you want to make sure that the module is installed, you can go to Admin → Stores → Configuration → Advanced → Advanced and check that the module is present in the list or you can open app/etc/config.php and check the array for the ‘Inchoo_Helloworld’ key, whose value should be set to 1.

Creating a controller

1. First we need to define the router. To do this, create a routes.xml file in the app/code/Inchoo/Helloworld/etc/frontend folder with the following code:

<?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="Inchoo_Helloworld" />
        </route>
    </router>
</config>

Here we’re defining our frontend router and route with an id “helloworld”.

The frontName attribute is going to be the first part of our URL.

In Magento 2 URL’s are constructed this way:
<frontName>/<controler_folder_name>/<controller_class_name>

So in our example, the final URL will look like this:

helloworld/index/index

2. Now we create the Index.php controller file in the app/code/Inchoo/Helloworld/Controller/Index folder with the following code:

<?php
 
namespace Inchoo\Helloworld\Controller\Index;
 
use Magento\Framework\App\Action\Context;
 
class Index extends \Magento\Framework\App\Action\Action
{
    protected $_resultPageFactory;
 
    public function __construct(Context $context, \Magento\Framework\View\Result\PageFactory $resultPageFactory)
    {
        $this->_resultPageFactory = $resultPageFactory;
        parent::__construct($context);
    }
 
    public function execute()
    {
        $resultPage = $this->_resultPageFactory->create();
        return $resultPage;
    }
}

In Magento 1 each controller can have multiple actions, but in Magento 2 this is not the case. In Magento 2 every action has its own class which implements the execute() method.

Creating a block

We’ll create a simple block class with the getHelloWorldTxt() method which returns the “Hello world” string.

1. Create a Helloworld.php file in the app/code/Inchoo/Helloworld/Block folder with the following code:

<?php
namespace Inchoo\Helloworld\Block;
 
class Helloworld extends \Magento\Framework\View\Element\Template
{
    public function getHelloWorldTxt()
    {
        return 'Hello world!';
    }
}
Creating a layout and template files

In Magento 2, layout files and templates are placed in the view folder inside your module. Inside the view folder, we can have three subfolders: adminhtml, base and frontend.
The adminhtml folder is used for admin, the frontend folder is used for frontend and the base folder is used for both, admin and frontend files.

1. First we will create a helloworld_index_index.xml file in the app/code/Inchoo/Helloworld/view/frontend/layout folder with the following code:

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd" layout="1column">
    <body>
        <referenceContainer name="content">
            <block class="Inchoo\Helloworld\Block\Helloworld" name="helloworld" template="helloworld.phtml" />
        </referenceContainer>
    </body>
</page>

Every page has a layout hand and for our controller action the layout handle is helloworld_index_index. You can create a layout configuration file for every layout handle.

In our layout file we have added a block to the content container and set the template
of our block to helloworld.phtml, which we will create in the next step.

2. Create a helloworld.phtml file in the app/code/Inchoo/Helloworld/view/frontend/templates folder with the following code:

<h1><?php echo $this->getHelloWorldTxt(); ?></h1>

$this variable is refrencing our block class and we are calling the method getHelloWorldTxt() which is returning the string ‘Hello world!’.

And that’s it. Open the /helloworld/index/index URL in your browser and you should get something like this:

helloworld

In case you feel you need some extra help, we can offer you a detailed custom report based on our technical audit – feel free to get in touch and see what we can do for you!


About Hrvoje Ivancic

Backend Developer

Hrvoje is a Backend Developer with love for the code and old cars.

Read more posts by Hrvoje / Visit Hrvoje's profile

67 comments

  1. Nice tutorial .Worked fine.
    Cache is disabled fine.But reindex cannot be done both from the backend and the command line.
    (php bin/magento indexer:reindex).This is the command I’m using. Tried sudo too.This is the error I’m getting if I hit the command.
    [InvalidArgumentException]
    There are no commands defined in the “indexer” namespace.

  2. I have one issue, I have created 2 modules in magento2. It’s both conflict route id.
    This module I follow by your sample helloworld.

    1***. In Localhost
    —————————-
    1. contact us: etc/frontend/routes.xml

    *** Contact us, It’s not work
    *** Helloworld, It’s work

    *** Contact us, It’s work but it display .phtml of helloworld
    *** Helloworld, It’s not work

    2.Helloworld: etc/frontend/routes.xml

    2*** In Hosting
    ———————–
    https://www.atomicgolf.shop/contact_us/
    https://www.atomicgolf.shop/helloworld/

    *** Both not work, although I change route id like localhost

    I want to you help me to solve this issue, what or why cause it from?

    Regard,
    Chheng

  3. namespace Inchoo\HelloWorld\Block\Index;

    class Index extends \Magento\Framework\View\Element\Template {

    public function __construct(\Magento\Catalog\Block\Product\Context $context, array $data = []) {

    parent::__construct($context, $data);

    }

    protected function _prepareLayout()
    {
    return parent::_prepareLayout();
    }

    public function getHelloWorldTxt()
    {
    return ‘anjali reddy’;
    }
    }
    you should create inside block folder index/index.php and writhe the above code inside it.

  4. This is really a Great tutorial to start with Magento 2, I developed my first module and everything described here is very simple, concise and easy to understand.
    Thank You Inchoo, Happy Coding

  5. Hello Hrvoje Ivancic,
    Thank you for the Hello World post, it’s working perfectly.
    I have built my first extension from Inchoo say HelloWorld.

  6. @Hrvoje Ivancic
    I want to add a MassAction in Order Grid in Magento2.
    I add xml in view/adminhtml/ui_component/sales_order_grid.xml.By adding this XML MassAction is show in dropdown.But when I select the MassAction I did not get the order ids in post request.

    Please help me in to find out how to get order ids via custom MassAction in MassAction controller in Magento2 ?

  7. i got this issue i tried to insatall the dom also but issue remain same.

    user@user:/opt/lampp/htdocs/magento2$ php bin/magento setup:upgradePHP Fatal error: Uncaught Error: Class ‘DOMDocument’ not found in /opt/lampp/htdocs/magento2/vendor/magento/framework/Config/Dom.php:364
    Stack trace:
    #0 /opt/lampp/htdocs/magento2/vendor/magento/framework/Config/Dom.php(109): Magento\Framework\Config\Dom->_initDom(‘__construct(‘_createConfigMerger(‘Magento\\Framewo…’, ‘_readFiles(Object(Magento\Framework\Config\FileIterator))
    #4 /opt/lampp/htdocs/magento2/vendor/magento/framework/App/ObjectManagerFactory.php(269): Magento\Framework\Config in /opt/lampp/htdocs/magento2/vendor/magento/framework/Config/Dom.php on line 364

    1. Follow these commands and then refresh your page.

      terminal — > in root directory -> php bin/magento setup:static-content:deploy
      terminal — > in rrot directory -> php bin/magento indexer:reindex
      Change ownership chown -R www-data:www-data /var/www/html/project-folder
      change permission chmod -R 755 /var/www/html/project-folder
      change permission chmod -R 777 /var/www/html/project-folder/var
      change permission chmod -R 777 /var/www/html/project-folder/pub
      clear cache rm -rf /var/www/html/project-folder/var/cache/*

      php bin/magento setup:upgrade
      php bin/magento setup:di:compile
      php bin/magento indexer:reindex

      Happy Coding 🙂

  8. 1 exception(s):
    Exception #0 (Magento\Framework\Exception\LocalizedException): Invalid Document
    Element ‘route’: Duplicate key-sequence [‘helloworld’] in unique identity-constraint ‘uniqueRouteFrontName’.
    Line: 4

    Exception #0 (Magento\Framework\Exception\LocalizedException): Invalid Document
    Element ‘route’: Duplicate key-sequence [‘helloworld’] in unique identity-constraint ‘uniqueRouteFrontName’.
    Line: 4

  9. I am getting error 404 not found. i am in developer mode but not getting any error.

  10. I followed step by step but getting 404 Not Found

    “The page you requested was not found, and we have a fine guess why.”

    What am I doing wrong? I noticed that there are mixed upper and lower case in the folder names in the example. Will this have caused 404?

    Please advise.

  11. Showing an error

    There has been an error processing your request
    Object DOMDocument should be created.

  12. am doin two-factor authentication….in mean-time am getting struct…so how do enable and disable the screen which gonna get after our usual screen …I have an menu and drop-down…which has two option…how do we get enable the screen when this gets…true
    give me some tips for this…

  13. Hi, i’m kinda lost, I have made everything explained here, the module Inchoo_Hellorworld is enabled and appears in the store->configuration->advanced, but the URL monsite.fr/helloworld/index/index returns 404 not found…
    I have the route.xml, I even added a composer.json to the root of the module, but I can’t make it work…
    I’m on developer mode , cache disabled, I have done a magento setup:upgrade and a setup:di:compile after that, I really am lost^^”

    P.S: Sorry for my english, i’m french.

    1. Oh, one last detail, I also tried to change xsi:noNamespaceSchemaLocation=”../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd”
      in Helloworld_index_index.xml because that path is invalid, so I’ve put vendor/magento/framework/view/layout/etc/page_configuration.xsd which is the good path for me. (Installed magento2 with command line and composer).

    2. Hello GrimWeiss
      Dont change it just check your layout file name with spelling and use lowercase.
      Also Please run this command
      php bin/magento setup:upgrad
      php bin/magento setup:static-content:deploy
      php bin/magento cache:flush
      Hope this will work

  14. Hello it is working perfectly fine for me. Just one question for example i wanted to change the name of frontend from “helloword” to lets say “hellousa” so i changed it in routes.xml but then it”/hellousa/index/index” started showing me 404 why? do i have to do something else to make it working?

  15. can any one help me to solve how to change the theme of header color(theme name:freego)?actuall theme of my magent2 is luma and later i overided to freego theme and i dont knw how to change the color of header and body background color as well.

  16. Hello) After “php bin/magento setup:upgrade” i have in terminal next problem: “[ErrorException] Undefined variable: subDirectory” and many errors instead my shop-page 🙁 What could be the problem?

  17. I followed all steps but stuck with this error don’t know where I am wrong can anyone assist please.

    1 exception(s):
    Exception #0 (BadMethodCallException): Missing required argument $context of Kkhatti\Helloworld\Controller\Index\Index.
    
    Exception #0 (BadMethodCallException): Missing required argument $context of Kkhatti\Helloworld\Controller\Index\Index.
    #0 /var/www/html/magento2/vendor/magento/framework/ObjectManager/Factory/Dynamic/Developer.php(82): Magento\Framework\ObjectManager\Factory\Dynamic\Developer->_resolveArguments('Kkhatti\\Hellowo...', Array, Array)
    #1 /var/www/html/magento2/vendor/magento/framework/ObjectManager/ObjectManager.php(57): Magento\Framework\ObjectManager\Factory\Dynamic\Developer->create('Kkhatti\\Hellowo...', Array)
    #2 /var/www/html/magento2/vendor/magento/framework/App/ActionFactory.php(40): Magento\Framework\ObjectManager\ObjectManager->create('Kkhatti\\Hellowo...')
    #3 /var/www/html/magento2/vendor/magento/framework/App/Router/Base.php(300): Magento\Framework\App\ActionFactory->create('Kkhatti\\Hellowo...')
    1. I just reinstall magento and follow all steps again and this time it works fine, Thanks.

    1. Hi guy. I have the same problem with you. I have followed all steps of this tutorial but when i run the code i received a blank page. Have you solved this problem, please tell me! thank you.

  18. I need to get some data from magento database and insert in another external database. Can someone tell me how? Some example/tutorial?

    I’m newbie in magento, i don’t know how to do… Thanks.

  19. in app/code folder after we create the new folder inchoo and Helloworld folder inside the code folder tell me,we create the folder otherwise these folder is available in app/code/….

  20. Hi,
    I got the same error but it resolved after giving writable permission to the cache folder under var folder.
    Thanks

  21. Hi,
    I also got same error. But it is resolved only after giving the write permission to the cache directories under the var folder.
    Thanks,

  22. Could someone please straighten out whether modules go in app/code/[vendorname] or in vendor/[vendorname]? I was under the impression that the latter replaced the former early in Magento 2.0, yet this article is dated Aug 2016 and references M2.1. I’m very confused.

    1. Your custom modules should be placed in app/code//

      Depending on where you got your Magento installation, the core code could be in either place. The Composer package (and I think the zip file on magento.com) will have the core code in vendor/magento, whereas the GitHub codebase will have it in app/code/Magento.

      Regardless of where the core code is, however, you should keep your custom modules in app/code//. The vendor folder is meant for packages that are integrated with (and shipping with) Magento. I hope this helped!

  23. hi i want to remove the last name field out of the create account page how do I write the module for it?

  24. Hi,
    i have tested your code in magento 2.1.1 and it gives blank page if you don’t add this:

    layout=”1column”

    to the file handle in layout like that:

  25. Hello,
    In the header I am getting 404 not found, but the module was loaded and I was able to print hello world. Is it supposed to 404 or there is a problem?

    1. I have same problem. Check all your code, it is likely typo. My problem was in name of file etc/frontend/routes.xml (I wrote routers.xml)

    2. i don’t have problem about routes.xml
      my controller does not work stiil 404 page not found

    3. Fixed the 404 issue for me, controller must have a folder called Index in which the index.php resides

      eg /code/NAMESPACE/Helloworld/Controller/index/index.php

    4. Surf’s reply worked for me

      controller must have a folder called Index in which the index.php resides

      Please note folder name is having capital “I” and file name small “i”

      After that /helloworld/index path worked for me

  26. Hello Hrvoje Ivancic!!
    where is code folder in app folder??
    where i create app/code/Inchoo/Helloworld??
    pls hepl me???
    thanks

  27. Hello Hrvoje Ivancic!! Thank you for your post, its working perfectly. But do you know why every time magento2 gives errors in console for js and css files?? And yes i am developing on local server. Thanks in advance. 🙂

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.