Magento Tutorials

How to Create a Custom Controller in Magento 2

Controllers in Magento 2 Overview

As a class located in module controller folder, controller is responsible for specific URL or group of URLs. In Magento 2, the controller is an important part of MVC flow. In comparison with Magento 1, controllers in Magento 2 are structured and they work in a different way.

When Magento 1 controllers have multiple actions, Magento 2 controllers have only one execute method that is called by front controller.

For every action we have one controller class with execute method. Execute method is called when router matches controller action class, and it’s responsible for returning response to front controller.

There are two types of controller: frontend and admin. They have similar workflow but admin controller has additional methods for permission checks.

Create a Custom Controller in Magento 2

To create a custom controller, we need to go through these steps:

Step 1: Create routers.xml File

Create routes.xml in etc/frontend for frontend controller or etc/adminhtml folder for admin controller.
 
Example:

etc/frontend/routes.xml – routes configuration for frontend; for demonstration we will match “magentofronttest” as frontname (part of url after domain name – for example: www.magentotest.net/magentofronttest/)

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
    <router id="standard">
        <route id="magentotestfrontend" frontName="magentofronttest">
            <module name="Magento_CustomControllers" />
        </route>
    </router>
</config>

Step 2: Custom configuration of controller

Add your custom configuration for controller in routes.xml, for example:
– router: id – standard(frontend)/admin
– route: id – your unique route id
– route: frontName – unique name in url, this is first part of url in base router (www.yourwebsite.com/frontName/actionpath/actionclass/)
frontName – set in routes.xml configuration, and has unique value which will be matched by router
 
action path – folder name inside Controller folder, default is index
action class – our action class which we call Controller, default is index
– module name – your module name
 
Example:

etc/adminhtml/routes.xml – routes configuration for admin, for demonstration we will match “magentoadmintest” as frontname (part of url after /admin/)

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
    <router id="admin">
        <route id="magentoadmintest" frontName="magentoadmintest">
            <module name="Magento_CustomControllers" before="Magento_Backend" />
        </route>
    </router>
</config>

Step 3: Create action controller

Create your action class following the url structure above:
Controller/Actionpath/Actionclass.php

Now we will create action classes for both of the controllers configuration.

On frontend let’s create action path and action class for url siteurl/magentoronttest/demonstration/sayhello/.

You can see that we need Demonstration folder (this is called action path) inside of our Controller folder, and inside that folder we need Sayhello.php controller action class:

Controller/Demonstration/Sayhello.php:

<?php

namespace Magento\CustomControllers\Controller\Demonstration;

class Sayhello extends \Magento\Framework\App\Action\Action
{
/**
* say hello text
*/
public function execute()
{
die("Hello – Magento\\CustomControllers\\Controller\\Demonstration\\Sayhello – execute() method");
}
}

For admin controller let’s match url siteurl/admin/magentoadmintest/demonstration/sayadmin/. 

For that we need Demonstration folder in Controller/Adminhtml, and inside that action class we need to create Sayadmin.php

Controller/Adminhtml/Demonstration/Sayadmin.php

<?php

namespace Magento\CustomControllers\Controller\Adminhtml\Demonstration;

class Sayadmin extends \Magento\Backend\App\Action
{
/**
* say admin text
*/
public function execute()
{
die("Admin – Magento\\CustomControllers\\Controller\\Adminhtml\\Demonstration\\Sayadmin – execute() method");
}
}

Note that by default _isAllowed will return true, and for creating custom permission you must add check under that method. For demonstration we will keep default value so user can access that controller.

Note: after you add new controller, flush everything from console in Magento root:

php bin/magento setup:upgrade

Hope this helps!


See also:
How to Create a Custom Module in Magento 2
Add a Custom Link to Magento 2 Admin Menu