Search code examples
phpstructurephalconmulti-modulehmvc

Module not loading in Phalcon multi module


I have a problem for loading a module.php in multimodule.

Here Directory structure for my app

this the Cores\Application

<?php
namespace Cores;

use \Phalcon\Di\FactoryDefault,
    \Phalcon\Loader,
     //\Phalcon\Registry,
    \Phalcon\Mvc\Router,
    \Phalcon\Mvc\Application as PhalconApplication,
    \Phalcon\Mvc\Events\Manager as EventsManager;

class Application extends PhalconApplication
{
    protected $_config;

    public function __construct()
    {
        $di = new FactoryDefault();

        $this->_config = Config::factory();
        parent::__construct($di);
    }

    private function __initModule()
    {
        $modulesDir = $this->_config->Config->application->modulesDir;
        $dir = [];

        /**
         * Faster way to load directory to find Modules
         */
        $objects = new \IteratorIterator(new \RecursiveDirectoryIterator($modulesDir));
        foreach($objects as $key => $ojb){
            if ($ojb->getFilename() != '.' AND $ojb->getFilename() != '..') {
                $dir[] = [
                    $ojb->getFilename() => [
                        'className' => 'Modules' . DS . $ojb->getFilename() . DS . 'Module',
                        'path'      => $ojb->getPath() .  '/' . $ojb->getFilename() . '/Module.php'
                    ]
                ];
            }
        }

        parent::registerModules($dir);
    }

    private function __initRoute()
    {
        $di = $this->getDI();
        $loader = new loader();
        $loader
            ->registerDirs([BASEPATH . 'App/Libraries/'])
            ->register();

        $di->set('router', function () {
            $router = new Router();

            $router->setDefaultModule('Administrator');

            $router->add('/:controller/:action', [
                'module'     => 'Modules\Administrator',
                'controller' => 1,
                'action'     => 2,
            ])->setName('Administrator');

            return $router;
        });
    }

    public function run()
    {
        $this->__initModule();
        $this->__initRoute();
        //echo '<pre>'.var_export($this->getModules(), true).'</pre>';
        try {
            echo $this->handle()->getContent();
        } catch (\Exception $err) {
            echo '<pre>'.var_export($err, true).'</pre>';
        }
    }
}

and this is the Modules\Administrator module.php

<?php
namespace Modules\Administrator

use \Phalcon\Loader,
    \Phalcon\Mvc\View,
    \Phalcon\DiInterface,
    \Phalcon\Mvc\Dispatcher,
    \Phalcon\Mvc\ModuleDefinitionInterface;

class Module implements ModuleDefinitionInterface
{
    /**
     * Register a specific autoloader for the module
     */
    public registerAutoloaders(DiInterface $di = null)
    {
        $loader = new Loader();

        $loader->registerNamespaces(
            [
                'Modules\\Administrator\\Controllers' => APP_PATH . '/Modules/Administrator/Controllers',
                'Moduels\\Administrator\\Models' => APP_PATH . '/Modules/Administrator/Models'
            ]
        );

        $loader->register();
    }

    /**
     * Register specific services for the module
     */
    public registerServices(DiInterface $di = null)
    {
        $di->set('dispatcher', function () {
            $dispatcher = new Dispatcher();

            $dispatcher->setDefaultNamespaces('Modules\\Administrator\\Controllers');

            return $dispatcher;
        });

        $di->set('view', function () {
            $view = new View();

            $view->setViewsDir(APP_PATH . 'Administrator/Views/');

            return $view;
        });
    }
}

I think I was write "like" phalcon multi module in their site but the module.php is not loaded, why?

The err says Module \'Administrator\' isn\'t registered in the application container

Please explain this to me!


Solution

  • 1. You don not need use \RecursiveDirectoryIterator.

    $objects = new \IteratorIterator(new \RecursiveDirectoryIterator($modulesDir));
    

    You need folders only from first level

    $objects = new \IteratorIterator($modulesDir);
    

    2. Mistake with slash/backslash and main error is structure of array. Check structure in article https://docs.phalconphp.com/en/3.0.1/reference/applications.html#multi-module

    $dir[] = [
        $ojb->getFilename() => [
             'className' => 'Modules' . DS . $ojb->getFilename() . DS . 'Module',
             'path'      => $ojb->getPath() .  '/' . $ojb->getFilename() . '/Module.php'
        ]
    ];
    

    Must be

    $dir[$ojb->getFilename()] = [
         'className' => 'Modules\\' . $ojb->getFilename() . '\\Module',
         'path'      => $ojb->getPath() .  DS . $ojb->getFilename() . DS . 'Module.php'
    ];
    

    3. In routes mistake in module name

    $router->add('/:controller/:action', [
        'module'     => 'Modules\Administrator',
        'controller' => 1,
        'action'     => 2,
    ])->setName('Administrator');
    

    Must be

    $router->add('/:controller/:action', [
        'module'     => 'Administrator',
        'controller' => 1,
        'action'     => 2,
    ])->setName('Administrator');