Is it possible to use dynamic controller name in routing in CodeIgniter 4?

Viewed 608

I want to use route localization like said here https://codeigniter.com/user_guide/outgoing/localization.html#in-routes

So I need to add route rule like: $routes->get('{locale}/books', 'App\Books::index');

But I want to make this rule for all controllers - not to specify rules for all controllers. So I added the rule: $routes->add('{locale}/(:segment)(:any)', '$1::$2');

I have controller Login with method index(). When I go to mydomain.com/Login method index() is loaded successfull. But when I go to mydomain.com/en/Login (as I expect to use my route) I got 404 Error with message - "Controller or its method is not found: \App\Controllers$1::index". But locale is defined and set correctly.

If I change my route to $routes->add('{locale}/(:segment)(:any)', 'Login::$2'); then mydomain.com/en/Login is loaded successfull as I want. But in this way I have to set routes for every controller and I want to set one route to work with all controllers.

Is it possible to set route with setting of dynamic controller name?

1 Answers

I'm not sure it is possible directly, but here is a workaround:

$routes->add('{locale}/(:segment)/(:any)', 'Rerouter::reroute/$1/$2');

Then, your Rerouter classlooks like this:


<?php namespace App\Controllers;

class Rerouter extends BaseController
{
    public function reroute($controllerName, ...$data)
    {
        $className = str_replace('-', '', ucwords($controllerName)); // This changes 'some-controller' into 'SomeController'.
        
        $controller = new $className();
        if (0 == count($data))
        {
            return $controller->index(); // replace with your default method
        }

        $method = array_shift($data);

        return $controller->{$method}(...$data);
    }
}

For example, /en/user/show/john-doe will call the controller User::show('john-doe').

Related