Zend Framework 2 child regex and literal routing

944 views Asked by At

Based on this stackoverflow question 15077075 i have accomplished that my application has a regex based route so i can pass this to my view and edit action.

  • app/123 - app controller view action (get by article id)
  • app/name-of-article - app controller view action (get by article name)
  • app/123/edit - app controller edit action (article id)
  • app/name-of-article/edit - app controller edit action (article name)
  • app/search/{search-string} - app controler search action (currently only accepts a searchstring without spaces and special characters)

This i have accomplished with the code below and is similar to the code in the link above:

'app' => array(
    'type'    => 'literal',
    'options' => array(
        'route'    => '/app',
        'defaults' => array(
            'controller' => 'App\Controller\App',
            'action'     => 'index',
        ),
    ),
    'may_terminate' => true,
),
'view' => array(
    'type' => 'regex',
    'options' => array(
        'regex' => '/app/(?<view>[a-zA-Z0-9_-]+)',
        'defaults' => array(
            'controller' => 'App\Controller\App',
            'action' => 'view',
        ),
        'spec' => '/app/%view%',
    ),
    'priority' => -1000,
),
'edit' => array(
    'type' => 'regex',
    'options' => array(
        'regex' => '/app/(?<view>[a-zA-Z0-9_-]+)/(?<edit>[a-zA-Z0-9_-]+)',
        'defaults' => array(
            'controller' => 'App\Controller\App',
            'action' => 'edit',
        ),
        'spec' => '/app/%view%/%edit%',
    ),
    'priority' => -1000,
),

I have twoone issue the first is that the url viewhelper doesn't recognize my routes

$controller = app
$action = recent
$this->url( $controller, array( 'action' => $action ) )

it just prints /app instead of /app/recent,

The same occurs when $action = 'search' or $action = 'new' it only prints /app


the second is that the search is recognized to its controller action only it fails when i put spaces or special characters in it

when i try to add \s in the constraints of the searchkey ( '[\sa-zA-Z0-9_-]+' ) it routes to the edit function

the route of search looks like this

Edited the route to this and it worked

'search' => array(
    'type' => 'literal',
    'options' => array(
        'route' => '/app/search',
        'defaults' => array(
            'controller' => 'App\Controller\App',
            'action'     => 'search',
        ),
    ),
    'may_terminate' => true,
    'child_routes' => array(
        'search' => array(
            'type' => 'segment',
            'options' => array(
                'route' => '/[:searchkey]',
                'constraints' => array(
                    'searchkey' => '[a-zA-Z0-9_\+-]+'
                ),
                'defaults' => array(
                    'action' => 'search'
                ),
            ),
        ),
    ),
),

i hope it's clear what i want if any code snippits are needed please ask

1

There are 1 answers

0
Pinpoint On BEST ANSWER

Sorted it out!
If one needs to get routes in his application this way you can use the code below

/App                        App/Index
/App/name-of-article        App/View
/App/123                    App/View
/App/name-of-article/edit   App/Edit
/App/123/edit               App/Edit
/App/recent                 App/Recent
/App/search                 App/Search
/App/new                    App/New

In my module.config.php i changed the route to:

'app' => array(
    'type' => 'segment',
    'options' => array(
        'route' => '/app[/:action]',
        'constraints' => array(
            'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
            'id' => '[0-9]+',
        ),
        'defaults' => array(
            'controller' => 'App\Controller\App',
            'action' => 'index',
        ),
    ),
    'may_terminate' => true,
),

'search' => array(
    'type' => 'literal',
    'options' => array(
        'route' => '/app/search',
        'defaults' => array(
            'controller' => 'App\Controller\App',
            'action' => 'search',
        ),
    ),
    'priority' => 1,
    'may_terminate' => true,
    'child_routes' => array(
        'search' => array(
            'type' => 'segment',
            'options' => array(
                'route' => '/[:searchkey]',
                'constraints' => array(
                    'searchkey' => '[\sa-zA-Z0-9_\+-]+'
                ),
                'defaults' => array(
                    'action' => 'search'
                ),
            ),
            'priority' => 2,
            'may_terminate' => true,
        ),
    ),
),

'new' => array(
    'type' => 'literal',
    'options' => array(
        'route' => '/app/new',
        'defaults' => array(
            'controller' => 'App',
            'action' => 'recent',
        ),
    ),
    'priority' => 2,
),

'view' => array(
    'type' => 'regex',
    'options' => array(
        'regex' => '/app/(?<view>[a-zA-Z0-9_-]+)',
        'defaults' => array(
            'controller' => 'App\Controller\App',
            'action' => 'view',
        ),
        'spec' => '/app/%view%',
    ),
),

'edit' => array(
    'type' => 'regex',
    'options' => array(
        'regex' => '/app/(?<view>[a-zA-Z0-9_-]+)/(?<edit>[a-zA-Z0-9_-]+)',
        'defaults' => array(
            'controller' => 'App\Controller\App',
            'action' => 'edit',
        ),
        'spec' => '/app/%view%/%edit%',
    ),
),

If you need other routes you can just add a new literal route below te app route, make sure you don't forget to set the priority