Action Controller in the Magento 2 Custom Module
I've been building a custom module for Magento 2 and faced with the uncertainty around Action Controllers. The obvious thing, when you create a new controller in a custom module is to have as simple as possible file structure. But it is not a case.
Creating an Action Controller
During the implementation of an Action Controller you should consider 3 steps. The routing declaration of the custom Magento 2 module, which should specify a custom module route name. The ACL rule for a custom page and finally, an Action Controller, which will be triggered to render a page.
The thing is. In case you have a module route name only in the URL, in my case it is a https://magento.com/custom_route/ where the "custom_route" is a declared frontName from the etc/frontend/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="admin"> <route id="custom_route" frontName="custom_route"> <module name="Pronko_CustomRoute" before="Magento_Backend" /> </route> </router> </config>
Then there is a question. What controller path should you have in the custom Magento 2 module for the Action Controller with the Index.php file name?
I was sure, that the app/code/Pronko/CustomRoute/Controller/Adminhtml/Index.php path is perfectly fine and the Front Controller would manage to find my controller. I was deadly wrong.
The Magento\Framework\App\Router\Base::matchAction method matches the "custom_route" from the URL and matches it according to the routes.xml file and gets the module name, which is in our case is a Pronko_CustomRoute.
Also, in order to prepare an action controller path and find the Action Controller, the default action and default controller name is used from the Magento\Framework\App\Router\Base class.
As a result, the Pronko\CustomRoute\Controller\Adminhtml\Index\Index class name will be prepared. Then this file is checked whether it exists and if not, the 404 action will be rendered. This is not what I was expecting.
Use Index directory together with Index Controller Class
Long story short. Always create an additional "Index" folder even if you have only one Action Controller in the Magento 2 custom module. Instead of Pronko\CustomRoute\Controller\Adminhtml\Index class name, which can be resolved to custom_route/index path, use the Pronko\CustomRoute\Controller\Adminhtml\Index\Index class name.
Why am I saying that? Well, it can save you 30-40 minutes of your time. Instead of debugging and looking for a reason, why the obvious naming convension in your module doesn't work, you may, for example, spend some time sharing knowledge over your blog. Or, building a Magento Admin User interface.
Do you think Magento 2 should support custom_route/index/index and custom_route/index pathes to match an Action Controller from your Magento 2 custom module?