1

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.

Community
  • 1
  • 1
Lena
  • 84
  • 6
  • Can you show the new configs after you changed the key to 'Vocabulary\Controller\Admin'? – Ruben Aug 19 '13 at 18:30

2 Answers2

2

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.

chandlermania
  • 360
  • 2
  • 8
  • In the last line of the question OP already said that the keys were changed to include the namespace. – Ruben Aug 20 '13 at 00:07
  • Thank you for the answer! I've already tried to change config as you recommended. In this case, everything is ok with default pages. But when I try to access page with not default controller, for example, lang/translation or vocabulary/add, I get 404 error. To be clear, error message is "The requested controller could not be mapped to an existing controller class. Controller: add(resolves to invalid controller class or alias: add)" System expects definition for "Add" controller according to router constraints array. It searches for "Add" invokable key, but not "Vocabulary\Controller\Add". – Lena Aug 20 '13 at 05:56
1

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.

Adrian
  • 1,370
  • 11
  • 21
  • 1
    Thanks! It works. Also, I tried not to set any action, and Router set "index" as a default. – Lena Aug 21 '13 at 05:23