ZF2 router configuration

675 views Asked by At

I'm newbie in ZF2, but I try to write an application. And I faced a problem with invokables and routing config.

I have 2 modules with configs:

<?php
return array(
'controllers' => array(
    'invokables' => array(
        'Index' => 'Vocabulary\Controller\IndexController'
        ,'Add' => 'Vocabulary\Controller\AddController'
        ,'Admin' => 'Vocabulary\Controller\AdminController'
    )
)
,'router' => array(
    'routes' => array(
        'vocabulary' => array(
            'type' => 'segment'
            ,'options' => array(
                'route' => '/vocabulary[/: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'
                )
            )
        )
    )
)

and

<?php
return array(
'controllers' => array(
    'invokables' => array(
        'Admin' => 'Lang\Controller\AdminController'
        ,'Translation' => 'Lang\Controller\TranslationController'
    )
)
,'router' => array(
    'routes' => array(
        'lang' => array(
            'type' => 'segment'
            ,'options' => array(
                'route' => '/lang[/:controller][/:action]'
                ,'constraints' => array(
                    'controller' => '[a-zA-Z][a-zA-Z0-9_-]*'
                    ,'action' => '[a-zA-Z][a-zA-Z0-9_-]*'
                )
                ,'defaults' => array(
                    'controller' => 'Admin'
                    ,'action' => 'index'
                )
            )
        )
    )
)

But on page /vocabulary/admin I see content of page /lang/admin. It seems, that problem is that invokable array's keys "Admin" are equal. How can I modify my config to make application work correctly? I want to keep "lang/admin" and "vocabulary/admin" paths.

I tried to use "Vocabulary\Controller\Admin" instead of "Admin" as invokable key, but it didn't help.

UPDATE

I solved the problem using this variant of configuration (I hope it will be helpful for somebody):

return array(
'controllers' => array(
    'invokables' => array(
        'Lang\Controller\Admin' => 'Lang\Controller\AdminController'
        ,'Lang\Controller\Translation' => 'Lang\Controller\TranslationController'
    )
)
,'router' => array(
    'routes' => array(
        'lang' => array(
            'type' => 'Literal'
            ,'options' => array(
                'route' => '/lang'
                ,'defaults' => array(
                    '__NAMESPACE__' => 'Lang\Controller',
                    'controller' => 'Lang\Controller\Admin'
                    ,'action' => 'index'
                )
            ),
            'may_terminate' => true,
            'child_routes' => array(
                '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(
                        ),
                    ),
                ),
            ),
        )
    )
)

In this case view helper command $this->url('lang', array('controller' => 'translation')) returns only "lang/", but I use $this->serverUrl('/lang/translation'); Both of modules work correctly.

2

There are 2 answers

1
Adrian On BEST ANSWER

To answer the last part of your question (as I agree with @ChanlderTi on the first part) :

In this case view helper command $this->url('lang', array('controller' => 'translation')) returns only "lang/"

This is because the "lang" route is a literal defining only "lang/". What you're trying to do is define the child route's url, whose full route name is "lang/default". So your code should be :

$this->url('lang/default', array('controller' => 'translation'))

You should probably define a default action for the child route also. Although I don't remember if the Router will default to index if no action is specified.

2
chandlermania On

You could simply define your invokables and routes using the full namespace as in

'controllers' => array(
    'invokables' => array(
        'Vocabulary\Controller\Index' => 'Vocabulary\Controller\IndexController'
        ,'Vocabulary\Controller\Add' => 'Vocabulary\Controller\AddController'
        ,'Vocabulary\Controller\Admin' => 'Vocabulary\Controller\AdminController'
    )
)

and

'controllers' => array(
    'invokables' => array(
         'Lang\Controller\Admin' => 'Lang\Controller\AdminController'
         ,'Lang\Controller\Translation' => 'Lang\Controller\TranslationController'

    )
)

and then adjust your defaults keys for each routing section to have the new key with the full namespace. i.e.

'defaults' => array(
    'controller' => 'Lang\Controller\Admin'
     ,'action' => 'index'
)

It's a personal preference to include the full namespace, as it makes it clearer to me where my code is pointing to. You don't have to do that, but the invokables for your controllers cannot be duplicated as this config is merged into one large config array with the last one defined winning. So your definition for the invokable key Admin as the Lang\Controller\AdminController overwrites your earlier assignment of that key to Vocabulary\Controller\AdminController.