2

I'm building a multi-site Zend Framework application using modules, sort of in the following structure:

|Project
    |-Application
        |-configs
        |-modules
            |-core
                |-controllers
                |-models
                |-views
                |-Bootstrap.php
            |-site1
                |-controllers
                |-models
                |-views
                |-Bootstrap.php
            |-site2
            |-site3
        |-Bootstrap.php
    |-Docs
    |-Library
    |-Public
    |-.zfproject.xml

Each module extends Core module.

I have the following in my module:

resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.modules[] = ""

What's the best way to Boostrap /application/modules/core/bootstrap.php and /application/modules/xxx/bootstrap.php where 'xxx' is the name of the module being loaded?

I could do it with a check at the top of every single Bootstrap method?

Or, should I be only adding the Module for the site I'm requesting alongside Core, and thus only two Bootstrap.php files would ever be loaded?

EDIT

If I remove the resources.modules[] = "" from my application.ini, and use the following code in my main Bootstrap.php to add a module, it appears to add the Controllers but not actually fire the Bootstrap.php located within the module?

$frontController = $this->getResource('frontController');
$frontController->addControllerDirectory(APPLICATION_PATH . '/modules/site1/controllers', 'site1');
3
  • See this post by MWOP. In particular, note that he recommends front-controller plugins that fire after routing is completed, check for the right module, and bail early otherwise. Commented Mar 1, 2012 at 1:47
  • David, please can you post this as an additional answer to this question? Commented Mar 1, 2012 at 10:12
  • @Sjwdavies: I'm also in need of core modules which are extended per site , just as your example. How did you do the routing to the correct site folder? Commented Apr 8, 2015 at 7:58

3 Answers 3

3

See the post by Matthew Weier O'Phinney:

Module Bootstraps in Zend Framework: Do's and Don'ts

In particular, note that he recommends front-controller plugins that fire after routing is completed, check for the right module, and bail early otherwise.

Sign up to request clarification or add additional context in comments.

4 Comments

This absolutely is the best answer. I have, instead, based on the link in your answer, created seperate FrontController plugins - one for each module and they are all included in Bootstrap.ini. These will spearhead the Facade pattern custom loading MWOP speaks of. I like this quote in particular from that post To re-iterate: if you have initialization tasks that should only be done if the module is the one being executed, do it in a front controller plugin or action helper.!
Yep, that post helped me a lot with my module-based apps. Thanks.
...and the post is gone. This is why it really isn't a good idea to just link to another page, put the answer here in SO for posterity.
That's why I added the general upshot - use front-controller plugins that fire after bootstrap. But your point is well taken. A more detailed summary would have been better. Updated the link which I found with a Google search.
1

The purpose of the bootstrap is to initialise the application. So all module bootstraps will always be initialised on every request, along with the main application one. If you want to perform an operation depending on the module that was loaded the easiest way to do this is in a controller plugin. Inside the plugin you can check to see what the current module is and then run what you need to.

Alternatively, instead of adding the resources.modules[] = "" line in the config (which will automatically scan the modules directory adding all modules), you could manually add individual modules in the application bootstrap. This would allow you do add just the core one and the path related to whichever site is being viewed. I'm not sure if this is a good fit for what modules were designed for though.

You need to fire the module bootstraps manually as well:

require_once APPLICATION_PATH.'/modules/site1/Bootstrap.php';
$className = 'Site1_Bootstrap';
$moduleBootstrap = new $className($this);
$moduleBootstrap->bootstrap();

5 Comments

Thanks Tim. One of the reasons for using this is to check if a user is logged in. I considered the idea of using a Controller Plugin but thought it might be best for future-proofing to only load the relevant bootstrap files and move this method here.
Checking if the user is logged in definitely sounds like it would be better in a controller plugin than the bootstrap. In a plugin you can change the request params (to send the user to a login page for example).
Updated my answer with some code for the module bootstraps as well.
Thanks Tim. I've created a 'Check If Module/Class/Action' exists plugin that does similar to set the Request and Dispatch module values to the appropriate modules if the requested module/controller/action doesn't exist. I think on this occasion I may be best using a Controller Plugin. However, I'd still like to be able to specify a single module in application.ini, then load the module bootstrap thats required..
Thanks Tim. I employed your script in an _initFrontModules() method in my Bootstrap.php. I feel dirty using the Bootstrapper in this way TBH. Also, a point to note is that using the above method fires the 'sub-loaded' module Bootstrap.php before the main application/bootstrap.php
0
protected function _initAutoload(){

    $front = Zend_Controller_Front::getInstance();
    $front->setControllerDirectory(array( 'Default' => APPLICATION_PATH.'/modules/default/controllers', 'Other' => APPLICATION_PATH.'/modules/other/controllers' ));
    $front->setParam('useDefaultControllerAlways', true);
    $modules = $front->getControllerDirectory();
    $default = $front->getDefaultModule();

    $router = new Zend_Controller_Router_Rewrite();
    $request =  new Zend_Controller_Request_Http();
    $router->route($request);
    $current_module = ucfirst($request->getModuleName());

    foreach (array_keys($modules) as $module) {

        if ($module == $current_module) {
            $modelLoader = new Zend_Application_Module_Autoloader(array( 'namespace' => $module, 'basePath'  => $front->getModuleDirectory($module)));

            require_once $front->getModuleDirectory($module).'/Bootstrap.php';
            $className = $module.'_Bootstrap';
            $moduleBootstrap = new $className($this);
            $moduleBootstrap->bootstrap();
        }
    }

    return $modelLoader;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.