Search code examples
phpzend-routezend-framework2

Routing in Zend Framework 2, skip 'index' action in url but get id


I have a controller that can be invoked as modulename/xmlcoverage with index action and some other actions, let say testAction(). The url to this controller is xml/coverage.

The default way is then that xml/coverage maps to my index action. And that xml/coverage/test maps to testAction. If I need an id for testAction, the url would be like xml/coverage/test/33 for instance.

However, for index action, it would need to be xml/coverage/index/33 Where I would like it to be xml/coverage/33.

This is my route

'xmlcoverage' => array(
        'type'    => 'segment',
        'options' => array(
                'route' => '/xml/coverage[/:action][/:id]',
                'constraints' => array(
                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'id'     => '[0-9]+',
                ),
                'defaults' => array(
                        'controller' => 'modulename/xmlcoverage',
                        'action'     => 'index',
                ),
        ),
),

When trying the url xml/coverage/33, I believe 33 should map to id, as it doesn't match the regex of action and both are optional. And since it doesn't match an action, the default (index) should be used.

Instead I get an error saying that the url cannot be matched by routing. So for me, it acts as if the route was '/xml/coverage[/:action[/:id]]' because I for some reason have to specify action for it to recognize the id.

What am I doing wrong, and how can I get the urls to work as I'd like? Thanks.

EDIT: Here is a problem. Doing this in my view:

$this->url('xmlcoverage', array('action' => 'index', 'id' => $someid))

actually gives an URL on the form xml/coverage/1 which will crash! Changing the route to /xml/coverage[/:action[/:id]] will at least make the url helper produce working urls..


Solution

  • After talking and debugging with the nice ZF2 folks on IRC, we tracked down a bug in the routing.

    During the discussion I made a small example to my issue, which is here. As you can see from the var dump here, the action gets lost in the second case where it should default to "index".

    But if anyone needs this functionality to work right now, here are ways that fix it:

    1. Instead of having the route to be /test[/:action][/:id] have it to be /test[/:action[/:id]], then the url helper will add /index/ and at least it works.
    2. Make a new route where you only listen for /test[/:id] in addition to the other one.
    3. In your controller, do public function notFoundAction() { $view = new ViewModel($this->indexAction()); //etc} Kinda hacky, but with this bug it will dispatch a not found action, which you can piggyback.