zendframework / zend-router

Standalone routing implementation for HTTP and console requests
BSD 3-Clause "New" or "Revised" License
32 stars 20 forks source link

Segment routing and controller constraint #16

Closed ronald-hristov closed 7 years ago

ronald-hristov commented 8 years ago

In version 3.0.2 If I have the following Segment route

'application' => [
    'type'    => Segment::class,
    'options' => [
        'route'    => '/app[/:controller][/:action]',
        'constraints' => [
            'controller' => '[a-zA-Z][a-zA-Z0-9_-]+',
            'action'     => '[a-zA-Z][a-zA-Z0-9_-]+',
        ],
        'defaults' => [
            'controller'    => Controller\IndexController::class,
            'action'        => 'index',
        ],
    ],
],

And use the the new InvokableFactory for the IndexController like this

    'controllers' => [
        'factories' => [
            Controller\IndexController::class => InvokableFactory::class,
        ],
    ],

Following the url /app/index/index will result in a

The requested controller could not be mapped to an existing controller class.
Controller:
index(resolves to invalid controller class or alias: index) 

If I add this to the controllers part of the configuration

'invokables' => [
    'index' => Controller\IndexController::class,
],

the url will be matched correctly (So basically the controller constraint is expecting the full namespace to the controller). But this doesn't look like a solution, because the 'index' key will be overwritten by another Module's Index controller invokable.

chris-kruining commented 7 years ago

you are aware that your constraint requires you to have at least 2 characters? and I expect the reason this doesn't work ik because the default.controller doesn't match the constraint either because there are no \ allowed in the constraint. Hope this helps if still relevant :D

Xerkus commented 7 years ago

It is not considered a good practice to use controller placeholder. Declare explicit routes for each controller.

'application' => [
    'type'    => Literal::class,
    'options' => [
        'route'    => '/app',
        'defaults' => [
            'controller'    => Controller\AppController::class,
            'action'        => 'index',
        ],
    ],
    'may_terminate' => true,
    'child_routes' => [
        'index' => [
            'type' => Segment::class,
            'options' => [
                'route'    => '/index[/:action]',
                'constraints' => [
                    'action' => '[a-zA-Z][a-zA-Z0-9_-]+',
                ],
                // defaults inherited
            ],
        ],
        'foo' => [
            'type' => Segment::class,
            'options' => [
                'route'    => '/foo[/:action]',
                'constraints' => [
                    'action' => '[a-zA-Z][a-zA-Z0-9_-]+',
                ],
                'defaults' => [
                    'controller' => Controller\FooController::class,
                ],
            ],
        ],
    ],
],