phpzend-framework2zend-config

ZF2: Groups of modules


I'm in the process of learning ZF2 and planning an application.

I would like to have 1 application with several groups of modules. Each group of modules could contain up-to 20+ modules.

I won't be able to guarantee a unique name for any of the modules for the whole app, but i can guarantee their uniqueness within their module group.

Ideally route requests to module groups using a Hosting router.

e.g. http://admin.mysite.com/foo/ => 'Admin/Foo/Index/Index',

http://special.mysite.com/foo/ => 'Special/Foo/Index/Index'

Idea #1

I was hoping to use a different module_path for each module group and namespacing the module path around the module group to determine uniqueness of the module's class. But modules sent to the module_autoloader only seem to pay any attention to the first part of any strings passed.

e.g.

array('modules' => array(
 'Admin\Admin','Admin\Bob','Admin\Users'
));

This gets strange behaviour I don't understand:

I've managed to fix this with some small alterations to the templateInjecter but it seems messy.

Idea #2

Just prefix module names to their subdirectory e.g.

namespace AdminAdmin\Controller,
class  IndexController {}

Thoughts

Question:


Solution

  • My interpretation of your question is that you're really asking two questions:

    (1) Namespacing modules

    This is possible natively with ZF2. Modules in ZF2 are basically just PHP namespaces, so a module named Foo\Bar is perfectly acceptable, and by default the module loader will look for it's module class in module/Foo/Bar then vendor/Foo/Bar.

    For example, if you wanted to create a module Anvil and under the namespace Acme, you would create directory module/Acme/Anvil, and inside it create a Module.php file:

    <?php
    namespace Acme\Anvil;
    
    class Module
    {
        /* module class code goes here */
    }
    

    In your application's config/application.config.php you would add Acme\Anvil to the modules key:

    return array(
        'modules' => array(
            'Application',
            'Acme\Anvil',
        ),
        // Remaining bits of config array are unchanged
    );
    

    (2) Dynamically-loading modules

    One approach you could take would be to modify your site's bootstrap index.php to modify the configuration on-the-fly based on the hostname. For example, using ZendSkeletonApplication you would set up your application.config.php file like so:

    <?php
    return array(
        'modules' => array(
            'Application',
            // Other modules common to all sites go here
        ),
        'sites' => array(
            'site-one.mydomain.com' => array(
                'modules' => array(
                    'ModuleOne',
                    'ModuleTwo',
                ),
            ),
            'site-two.mydomain.com' => array(
                'modules' => array(
                    'ModuleThree',
                ),
            ),
        ),
        // Remaining bits of config array are unchanged
    );
    

    To make this work we make a slight modification to public/index.php to intercept the configuration array loaded from config/application.config.php and reconfigure the modules key:

    // Pick host out of request
    $hostname = $_SERVER['HTTP_HOST'];
    
    // Load application configuration
    $applicationConfig = require 'config/application.config.php';
    
    // Merge site-specific modules into loaded modules array
    $applicationConfig['modules'] = array_merge(
        $applicationConfig['modules'],
        $applicationConfig['sites'][$hostname]['modules']
    );
    
    // Run the application!
    Zend\Mvc\Application::init($applicationConfig)->run();
    

    This approach provides an easy way to change which modules are loaded for a particular hostname, but can easily be extended to allow site-specific configuration file autoloading and site-specific module directories as well.