-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Dispatch to another module in a multi-module app #121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hi Lee, a dispatcher can't forward to modules outside the current module. This happens because controllers might be located at any directory and have any namespace, suffix, prefix, etc. If you want to forward to other module you may use a temporary HTTP redirection: $response->redirect("backend/user/login"); http://docs.phalconphp.com/en/latest/reference/response.html#making-redirections |
That's ok I think. |
I really love Phalcon. Please don't get me wrong. I'm very happy with most of the framework. However, it might be nice to offer some functionality to at least facilitate the possibility. Multi module apps very useful but it would be so much better if you would not have to hack the pieces together. As a developer being used to Zend Framework it feels a little unnatural to not being able to share such functionality accross my modules. The code used above should - in my opinion - just work. Assuming all configurations are correct. That should be up to the developer. Using different folder structures should not break functionality. It should just require another kind of configuration. Zend framework solves this by firing an init event for each module being loaded.( It should not be cluttered with all kinds of operations. But it is a nice possibility to inject lazy loading services, attach events etc on a module to module basis. ) And zf basically collects a 'cachable' configuration object on bootstrap. (Routes, Services etc) Optionally overriding configurations/services in a logical order. Global config->Module config->User config. Also, by moving module configurations to the module itself it is much easier to reuse the module. Personally I believe it is good design practice to completely separate the module from the application. ZF uses a single autoload folder in the global config folder where you can put a modulename.config.php file allowing developers to override module configurations on a application to application basis to finetune the module if needed. This means that you would not have to change a well designed module in new applications. Just override the default module configuration. It may be a hassle to set it up. Especially for developers with little experience with frameworks. But then again. It gets easier pretty quick andm how great is it to be able to reuse essential modules accross different projects. Keeping them identical and separated is a real timesaver when it comes to maintainance. Again; The configuration should be cached in production. But I really believe it is a very elegant way to use modules. |
@DaanBiesterbos I have used ZF 1. ZF bootstrap approach looks like good design but not useful if you try to make extreme things. I looked up ZF 2 and looks like too many complex and there are too many unnecessary configurations. I left using ZF rewriting my projects with Phalcon. Phalcon has got very simple and efficient design. There are some missing features but I believe the Phalcon will be better and mature ongoing time. |
@tugrul I could'nt agree more. And I prefer Phalcon above ZF2 as well. Although the complexity in ZF is not so bad. It just takes a while to get used to. I not trying to say to solve phalcon issues the ZF way. Just the basic things that glues the components together would be nice. I'm sure phalcon will mature over time. Perhaps it is possible to get some beautiful shiny things from matured frameworks and only the things that has something to do with basic functionality. Like forwarding to other modules :p That would be golden. And all I could possibly ask from a great framework with performance in mind. |
@DaanBiesterbos Access to component context is very hard in Zend because there is unnecessary encapsulation. For example i need to access Dispatcher instance and traversing is very hard generally and it forced me to use Zend_Registry. Phalcon DI is everywhere for example I can access the dispatcher parameter in view like $this->dispatcher->getParam('param') Another problem is performance. I used Zend_Navigation with 4k nodes and its terrible because generates tree every request and after find active node. I tried to store tree on the apc cache there is no use. I'm making my solution with mongodb now. |
Hmmmm.. I'm not very familiar with zend framework 1. I guess you are right. In zend framework 2 its not so bad. Solved the forward issue btw...I've not tested it very well. But for now it seems to do what I want.
/**
* Register application modules
*/
$application->registerModules(array(
'moduleA' => array(
'className' => 'MyApp\ModuleA\Module',
'path' => __DIR__ . '/../apps/moduleA/Module.php',
'metadata' => array(
// // Enable forwarding to other modules
'controllersNamespace' => 'MyApp\ModuleA\Controllers',
'controllerSuffix' => '',
'actionSuffix' => '',
),
),
'moduleB' => array(
'className' => 'MyApp\ModuleB\Module',
'path' => __DIR__ . '/../apps/moduleB/Module.php',
'metadata' => array(
// // Enable forwarding to other modules
'controllersNamespace' => 'MyApp\ModuleB\Controllers',
'controllerSuffix' => '',
'actionSuffix' => '',
),
),
));
// Attach to dispatch:beforeForward event
$modules = $application->getModules();
$di->getShared('eventsManager')->attach('dispatch:beforeForward', function($event, $dispatcher, array $forward) use($modules)
{
if(isset($forward['module'])){
// Check whether the module is registered
if(!isset($modules[ $forward['module'] ])){
throw new \Phalcon\Mvc\Dispatcher\Exception('Module ' . $forward['module'] . ' does not exist.');
}
// Check whether module contains meta data
$moduleData = $modules[ $forward['module'] ];
if(!isset($moduleData['metadata']) || !isset($moduleData['metadata']['controllersNamespace'])){
// @todo think of something nice to automatically get controller dir from existing config?
throw new \Phalcon\Mvc\Dispatcher\Exception('Module ' . $forward['module'] . ' does not have meta data. Controller namespace must be specified.');
}
// Set controller namespace
$metadata = $moduleData['metadata'];
$dispatcher->setNamespaceName($metadata['controllersNamespace']);
// Set controller suffix
if(isset($metadata['controllerSuffix'])){
$dispatcher->setControllerSuffix($metadata['controllerSuffix']);
}
// Set action suffix
if(isset($metadata['actionSuffix'])){
$dispatcher->setActionSuffix($metadata['actionSuffix']);
}
}
}); |
Ohw, and for clearity. I would use this to forward from module $this->dispatcher->forward(array(
'module' => 'moduleB ',
'controller' => 'index',
'action' => 'index'
)); |
Hmmm. There is a little gotcha with the view. Don't forget to set all paths for the view you are forwarding to. Personally I use the initialize() method on the base controller to set module specific configurations. ( registerServices in module.php does not seem to run when forwarding to other modules. The init event on the controllerbase does. I used this to set view paths. Works like a charm. ( For me ;-) ) $this->view->setBasePath(__DIR__ . '/../');
$this->view->setViewsDir('/views/');
// Layout template is located in view folder core module.
$this->view->setLayoutsDir('/../../../apps/core/views/layouts/');
$this->view->setPartialsDir('/partials/');
$this->view->setMainView('/../../../apps/core/views/index'); |
Maybe I'm wrong, but in version 1.2.4, you can specify the namespace for the "forward"? |
Hi everyone! So it's not possible to forward to another module, right? But also Phalcon\CLI\Console::handle() behaves a bit strange/unexpected.
This does not work (as described in this thread), the dispatcher tries to find controller LoremTask with IpsumAction in the same module. BUT: the bootstrap file of the "other" module is loaded! My question is: Is it possible to use e.g. public service classes from another module and if yes, what would be the best way to lazy bootstrap another module? Best |
Make the lazy loading is quite simple. But there is still a number of issues. |
Thanks a lot for links to your example! |
It is inevitable if you want multimodular. Otherwise your modules - just directories on the disk and nothing more. |
I'd like to see this implemented for the reason of 40_, 50_ pages, because I want to forward to an error controller/action which is global, rather than having one for each module. Right now I have a controller in each module which refers to the same view and extends the main error controller to solve this. |
Implemented in the |
@sergeyklay wow awesome! |
Though it's implemented just using event as i saw in test. Like now there is now clean and easy way to do it, but not out of box like |
Clarification ... it's not implemented. There is now a forward event that doesn't add anything new as any of the other events could easily be hooked. Module forwarding is a huge refactor to do it properly as a few API changes need to be made to the modules to register and de-register separate dispatchers and DI services cleanly all while keeping the same scope for the end user. |
I tried to modify the file
apps/library/Acl.php
in my test HMVC app base on https://github.com/phalcon/mvc/tree/master/multiple, changed the dispatcher code as followed:Thus want to dispatch to
backend/user/login
asmodule/controller/action
in some conditions.It doesn't work, just dispatch to the same module where the responding controller is. Any solution? Or should it be a new feature?
The text was updated successfully, but these errors were encountered: