Question

This is more of a curiosity than a "need".
I have a few controller actions that do exactly the same thing, just some parameters differ.
I'm trying to reduce the amount of code I write and have one single controller class and via di.xml configure that class using virtual types.
I know I can just create empty classes for each controller that extend a main controller action and configure them via di.xml, but I want to skip those too if possible.
I got from here that virtual types can be used as source models because they are instantiated via object manager.
Controllers are also instantiated via Object Manager, but I think things happen a little different.

I'm expecting an answer like:

  • this is not possible because...
  • yes, it's possible, here is how you can do it...
  • not sure it is possible but here is how you can test....
Was it helpful?

Solution

This isn't possible because the core routers build the action list using \Magento\Framework\Module\Dir\Reader::getActionFiles source, which loads the available actions by reading files contained in each module's Controller directory. Below is the function as it currently exists in 2.3-develop:

public function getActionFiles()
{
    $actions = [];
    foreach ($this->modulesList->getNames() as $moduleName) {
        $actionDir = $this->getModuleDir(Dir::MODULE_CONTROLLER_DIR, $moduleName);
        if (!file_exists($actionDir)) {
            continue;
        }
        $dirIterator = new \RecursiveDirectoryIterator($actionDir, \RecursiveDirectoryIterator::SKIP_DOTS);
        $recursiveIterator = new \RecursiveIteratorIterator($dirIterator, \RecursiveIteratorIterator::LEAVES_ONLY);
        $namespace = str_replace('_', '\\', $moduleName);
        /** @var \SplFileInfo $actionFile */
        foreach ($recursiveIterator as $actionFile) {
            $actionName = str_replace('/', '\\', str_replace($actionDir, '', $actionFile->getPathname()));
            $action = $namespace . "\\" . Dir::MODULE_CONTROLLER_DIR . substr($actionName, 0, -4);
            $actions[strtolower($action)] = $action;
        }
    }
    return $actions;
}

It may be possible to do this using custom router and action list classes, but it is not possible out of the box.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top