1
votes

Is it possible in ZF2 routing to have a generic parent route, matching all public actions, but override specific areas with a custom child-route and controller?

What I want:

/parent => matches parent controller
/parent/edit => matches parent controller editAction
/parent/childsection => matches child controller
/parent/childsection/edit => matches child controller editAction

I couldn't come up with any configuration that fits my needs. Following the config I thought would work - but ZF2 routes terminates at the parent route cause childsection could be an action too.

'parent' => array(
    'type' => 'Segment',
    'may_terminate' => true,
    'options' => array(
        'route' => '/parent[[/:action][/:id]]',
        'constraints' => array(
            'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
            'id' => '[0-9]+',
        ),
        'defaults' => array(
            'controller' => 'Application\Controller\Parent',
            'action' => 'index',
        ),
    ),
    'child_routes' => array(
        'child' => array(
            'type' => 'Segment',
            'options' => array(
                'route' => '/childsection/:action[/:id]',
                'constraints' => array(
                    'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                    'id' => '[0-9]+',
                ),
                'defaults' => array(
                    'controller' => 'Application\Controller\Child',
                ),
            ),
        ),
    ),
),

The only thing that worked was a minimal parent literal route and 2 child routes - 1 generic and 1 specific for the child section. But in this case I have to redirect or generate urls using ->toRoute('parent/default'...)

Is there any other elegant solution or is this simply not possible?

2

2 Answers

0
votes

I always tell people that they shouldn't use such regex for controller/action. Try using something more restricted like (edit|delete) instead and keep adding whitelisted actions to the list.

0
votes

You could always do something like

route => /foo[/:bar[/:baz[/:bing]]]

where bar, baz, bing would be action, child-controller and child-action and define them with constraints like you just did. I would then map this route to a SupervisorController with superviseAction.

This action would then check if a controller matching the given routename exists and if this controller then has the given action. Then you could fetch the controller and simply call the action.

However just like @grizzm0 said, this is unclean. It is very prone to errors and at some point you may not even know what is dispatched where. My personal preference (and those of most people around my circle as far as I know their style) would be to simply take the time and configure all routes by hand.

It is a little bit of work, yes, but you always know what's going on. Sometimes, less magic is more!