Kontynuujemy Smart Routes, choć w naszym projekcie z tego rozwiązania nie korzystaliśmy – ale jest warte odnotowania.

Klasa kontrolera:

<?php 
class UserAdmin {
    public function addNew(){
        return null;
    }
}

Coś, co z URLa przyszło jako kontroler:

$controller = 'uSeR-AdMIN';

Do małej:

echo strtolower($controller);
//user-admin

Słowa z wielkiej, myślnik jako separator słów:

echo ucwords(strtolower($controller), '-');
//User-Admin

Zamień myślnik na pusty string, kiedy już nie jest potrzebny:

echo str_replace("-", "", ucwords(strtolower($controller), '-'));
//UserAdmin

Teraz metoda:

class SmartDispatcher {
    public function getControllerName(array $params): string
    {
        $controller = $params["controller"];

        $controller = str_replace("-", "", ucwords(strtolower($controller), "-"));

        $namespace = "App\Controllers";

        return $namespace . "\\" . $controller;
    }

    //(...)
}

Użycie:

$smart = new SmartDispatcher;
$params = ['controller' => 'user-admin', 'action' => 'add-new'];

echo $smart->getControllerName($params) . "<br>";
//App\Controllers\UserAdmin <-- class

Ulepszamy metodę i to, jak pracuje z namespace:

class SmartDispatcher {
    public function getControllerName(array $params): string
    {
        $controller = $params["controller"];

        $controller = str_replace("-", "", ucwords(strtolower($controller), "-"));

        $namespace = "App\Controllers";

        if (array_key_exists("namespace", $params)) {

            $namespace .= "\\" . $params["namespace"];

        }

        return $namespace . "\\" . $controller;
    }

    //(...)
}

Pod domyślnym namespace (App\Controllers) dodajemy kolejny namespace:

$smart = new SmartDispatcher;
$params = ['controller' => 'user-admin', 'action' => 'add-new', 'namespace' => 'User'];

echo $smart->getControllerName($params) . "<br>";
//App\Controllers\User\UserAdmin 

Wszystko świetnie działa i nadaje się do dużych projektów a zarazem znając konwencję, nie musimy sami określać routes.