We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Register/Run All Module Autoloaders in Modular Structure

Hi,

I'm trying to built modular structure but i have an issue about cross modules access classes.

I want to register all module autoloaders in "/modules/xx/module.php"

I'm using registerAutoloaders in module.php but registered only current module.

I want to load all routes and access any models or any class of a module from anywhere.

May be i can make this with glob or defination one by one for all modules but i need more elegant solution.

Thanks

This is how i handle this in my application:

/**
 * We need all models, route and repository classes be available in every module so we register them all
 */
$namespaces = $cache->get('namespaces');
if (empty($namespaces)) {
    $namespaces = [
        'Suzuki\App\Validators' => __APP_DIR__.'/../App/Validators',
        'Suzuki\App\Exceptions' => __APP_DIR__.'/../App/Exceptions',
        'Suzuki\App\Factories' => __APP_DIR__.'/../App/Factories',
        'Suzuki\App\Interfaces' => __APP_DIR__.'/../App/Interfaces',
        'Suzuki\App\Services' => __APP_DIR__.'/../App/Services',
        'Suzuki\App\Abstracts' => __APP_DIR__.'/../App/Abstracts',
        'Suzuki\App\Helpers' => __APP_DIR__.'/../App/Helpers',
        'Suzuki\App\Dialect' => __APP_DIR__.'/../App/Dialect',
        'Suzuki\App\Providers' => __APP_DIR__.'/../App/Providers',
        'Suzuki\Module\Error' => __APP_DIR__.'/../Module/Error',
    ];
    foreach ($modules as $key => $value) {
        $module = ucfirst($key);
        $namespaces += ["Suzuki\\Module\\{$module}\\Model" => "../Module/{$module}/Model"];
        if ($module != 'Error') {
            $routeClasses += ["Suzuki\\Module\\{$module}\\Routes" => "../Module/{$module}/Routes.php"];
            $namespaces += ["Suzuki\\Module\\{$module}\\Repository" => "../Module/{$module}/Repository"];
        }
    }
    $cache->save('namespaces', $namespaces, 0);
    $cache->save('routeClassesFiles', $routeClasses, 0);
} else {
    $routeClasses = $cache->get('routeClassesFiles');
}
$loader->registerNamespaces($namespaces);
$loader->registerClasses($routeClasses);
$loader->registerFiles($filesClasses);
$loader->register();
/**
 * Mounting Routes
 */
$routeClasses = $di->get('cache')->get('routeClasses');
if (empty($routeClasses)) {
    $routeClasses = [];
    $aliasClasses = [];
    $aliasFiles = [];
    foreach ($modules as $key => $value) {
        $module = ucfirst($key);
        $routeClass = "Suzuki\\Module\\{$module}\\Routes";
        if (class_exists($routeClass)) {
            $routeClasses[] = $routeClass;
            $routeGroup = new $routeClass;
            $di->getShared('router')->mount($routeGroup);
        }
        $loader = new Loader();
        $loader->registerFiles([$value['path']]);
        $loader->register();
        if (method_exists($value['className'], 'registerNamespaceAlias')) {
            call_user_func([$value['className'], 'registerNamespaceAlias']);
            $aliasClasses[] = $value['className'];
            $aliasFiles[] = $value['path'];
        }
        $cache->save('routeClasses', $routeClasses, 0);
        $cache->save('aliasClasses', $aliasClasses, 0);
        $cache->save('aliasFiles', $aliasFiles, 0);
    }
} else {
    foreach ($routeClasses as $routeClass) {
        $routeGroup = new $routeClass;
        $di->getShared('router')->mount($routeGroup);
    }
    $aliasClasses = $di->get('cache')->get('aliasClasses');
    $aliasFiles = $di->get('cache')->get('aliasFiles');
    $loader = new Loader();
    $loader->registerFiles($aliasFiles);
    $loader->register();
    foreach ($aliasClasses as $aliasClass) {
        call_user_func([$aliasClass, 'registerNamespaceAlias']);
    }
}

Hi Ahmet make a bootstrap where you register a global directories and services, then load modules and in each module.php you can load or override services, etc., well, this is the way I am working today. Good luck