-->

Zend Framework 2 Routing subdomains to module

2019-01-14 09:15发布

问题:

After searching a long time with no success. before I give up, I would like to ask:

Is there a way to route a subdomain to a module in Zend Framework 2? like:

Subdomain => Module
api.site.com => api
dev.site.com => dev
admin.site.com => admin
site.com => public
...

I tried doing it like this but I can't get access to controllers other than the default (Index).

'router' => array(
    'routes' => array(
        'home' => array(
            'type' => 'Hostname',
            'options' => array(
                'route' => 'site.com',
                'defaults' => array(
                    '__NAMESPACE__' => 'Application\Controller',
                    'controller'    => 'Index',
                    'action'        => 'index',
                ),
            )
        )
    ),
),

Thank you for taking the time to help me.

回答1:

Zend Framework 2 doesn't have a notion of routing to modules; all routing mappings are between a URI pattern (for HTTP routes) and a specific controller class. That said, Zend\Mvc provides an event listener (Zend\Mvc\ModuleRouteListener) which allows you to define a URI pattern that maps to multiple controllers based on a given pattern, and so emulates "module routing". To define such a route, you would place this as your routing configuration:

'router' => array(
    'routes' => array(
         // This defines the hostname route which forms the base
         // of each "child" route
        'home' => array(
            'type' => 'Hostname',
            'options' => array(
                'route' => 'site.com',
                'defaults' => array(
                    '__NAMESPACE__' => 'Application\Controller',
                    'controller'    => 'Index',
                    'action'        => 'index',
                ),
            ),
            'may_terminate' => true,
            'child_routes' => array(
                // This Segment route captures the requested controller
                // and action from the URI and, through ModuleRouteListener,
                // selects the correct controller class to use
                'default' => array(
                    'type'    => 'Segment',
                    'options' => array(
                        'route'    => '/[:controller[/:action]]',
                        'constraints' => array(
                            'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
                            'action'     => '[a-zA-Z][a-zA-Z0-9_-]*',
                        ),
                        'defaults' => array(
                            'controller' => 'Index',
                            'action'     => 'index',
                        ),
                    ),
                ),
            ),
        ),
    ),
),

(Click here to see an example of this @ ZendSkeletonApplication)

This is only half of the equation, though. You must also register every controller class in your module using a specific naming format. This is also done through the same configuration file:

'controllers' => array(
    'invokables' => array(
        'Application\Controller\Index' => 'Application\Controller\IndexController'
    ),
),

The array key is the alias ModuleRouteListener will use to find the right controller, and it must be in the following format:

<Namespace>\<Controller>\<Action>

The value assigned to this array key is the fully-qualified name of the controller class.

(Click here to see an example of this @ ZendSkeletonApplication)

NOTE: IF you aren't using ZendSkeletonApplication, or have removed it's default Application module, you will need to register the ModuleRouteListener in one of your own modules. Click here to see an example of how ZendSkeletonApplication registers this listener



回答2:

If i understand slide #39 of DASPRIDS Rounter Presentation correctly, it's as simple as - on a per module basis - to define your subdomain hosts, i.e.:

'router' => array(
    'routes' => array(
        'home' => array(
            'type' => 'Hostname',
            'options' => array(
                'route' => 'api.site.com',
                'defaults' => array(
                    '__NAMESPACE__' => 'Api\Controller',
                    'controller'    => 'Index',
                    'action'        => 'index',
                ),
            )
        )
    ),
),

Etc, you'd do this for every Module on its own.