4

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....
3

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.