Issues

ZF2-486: Individual segments in a route are not filled when using url view helper and url controller plugin

Description

I have this application module config file in /module/Application/config/module.config.php

 
return array(
    'router' => array(
        'routes' => array(
            'home' => array(
                'type' => 'Literal',
                'options' => array(
                    'route'    => '/',
                    'defaults' => array(
                        'controller' => 'Application',
                        'action'     => 'index',
                    ),
                ),
            ),
            'application' => array(
                'type'    => 'segment',
                'options' => array(
                    'route'    => '[/:locale][/:controller][/:action][/:id]',
                    'constraints' => array(
                        'locale'     => '[a-z]{2}',
                        'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'action'     => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'id'         => '[0-9]+',
                    ),
                    'defaults' => array(
                        'controller' => 'Application',
                        'action'     => 'index',
                        'locale'     => 'de',
                    ),
                ),
                'may_terminate' => true,
                'child_routes' => array(
                    'default' => array(
                        'type'    => 'Wildcard',
                        'options' => array(
                        ),
                    ),
                ),
            ),
        ),
    ),
    'controllers' => array(
        'invokables' => array(
            'Application' => 'Application\Controller\IndexController',
        ),
    ),
);

The routing itself works perfectly. But when I want to create an Url with the url view helper or the url controller plugin I don't get the expected result. Here is an example from a view script:

 
<?php echo $this->url('application', array('locale' => 'de', 'action'=>'add', 'controller' => 'application')); ?>

And here from a controller:

 
echo $this->url()->fromRoute('application', array('action' => 'add', 'controller' => 'application', 'locale' => 'de'));

Both output

/application/add

and not the expected

/de/application/add

Renaming the locale segment or changing the order of the segments does not help. But when I clear the default for the locale then it does work.

Comments

corrected code blocks

Assigned to Shavar Evron by mistake

I've confirmed the reproduce case a this time, and will see if I can fix it.

Actually, in looking at it, the problem is with your route.

Because you have multiple optional segments that are not encapsulated, the router is getting confused about what is truly optional, and what is required. Couple this with a wildcard route, and it's really anybody's guess as to how this should be assembled.

If you rewrite the segment route string as follows, it works fine:


'route' => '[:locale[/:controller[/:action[/:id]]]]'

Based on the use cases you've presented so far, it appears this is what you really want -- the locale should always be the first segment, and it will be optionally followed by the controller, optionally followed by the action, and finally optionally followed by the identifier.

Thanks for your effort. Works now. And sorry for stuffing the issue tracker with this.

No worries -- it looked like a legitimate bug. It was only when I was tracing execution that I realized what was happening, and why.