3

I've successfully created my Route using Regex. I have Several Optional Parameters in my route that I don't want displayed in the URL Helper unless the user has specified them. How can I accomplish this?

This is what I currently have

        $route = new Zend_Controller_Router_Route_Regex(
        '([a-zA-Z-_0-9-]+)-Widgets(?:/page/(\d+))?(?:/limit/(\d+))',
        array(
            'controller'    => 'widget',
            'action'        => 'list',
        ),
        array(
            1 => 'color',
            2 => 'page',
            3 => 'limit'

        ),
        '%s-Widgets/'
    );

    $router->addRoute('color_widgets', $route);

I then call the URL Helper with following code

        echo $this->url(array('page' => $page), 'color_widgets', false); 

This results in /Blue-Widgets/ and does not send the Page to the URL. I can fix this by changing the reverse in the Router

    $route = new Zend_Controller_Router_Route_Regex(
        '([a-zA-Z-_0-9-]+)-Widgets(?:/page/(\d+))?(?:/limit/(\d+))',
        array(
            'controller'    => 'widget',
            'action'        => 'list',
            'page'      => 1
        ),
        array(
            1 => 'color',
            2 => 'page',
            3 => 'limit'

        ),
        '%s-Widgets/page/%d'
    );

However this doesn't solve my problem say I have a Url

/Blue-Widgets/page/1/limit/10 The limit doesn't show, again I can fix that with the following

    $route = new Zend_Controller_Router_Route_Regex(
        '([a-zA-Z-_0-9-]+)-Widgets(?:/page/(\d+))?(?:/limit/(\d+))',
        array(
            'controller'    => 'widget',
            'action'        => 'list',
            'page'      => 1,
            'limit'     => 10
        ),
        array(
            1 => 'color',
            2 => 'page',
            3 => 'limit'

        ),
        '%s-Widgets/page/%d/limit/%d'
    );

The problem with this is the user is at /Blue-Widgets/ and I want to take them to the next page of Blue Widgets with following code

        echo $this->url(array('page' => $page), 'color_widgets', false); 

They are actually taken to /Blue-Widgets/page/2/limit/10

When I actually want to take them to /Blue-Widgets/page/2

How can I accomplish this with the Zend Framework.

user1287238
  • 31
  • 1
  • 3

2 Answers2

2

It is not possible to use a regex reverse route with a variable number of values. You could:

  1. Write a different route for every optional parameter (not recommended)
  2. Use a different route structure

You could, for instance change your route to:

$route = new Zend_Controller_Router_Route(
    'widgets/:color/*',
    array(
        'controller'    => 'widget',
        'action'        => 'list',
        'page'      => 1,
        'limit'     => 10
    ),
    array(
        'color' => '[a-zA-Z-_0-9-]+',
        'page' => '\d+',
        'limit' => '\d+',
    )
);

Another option would be to create your own custom route class, which can parse and build the correct uri.

Pieter
  • 1,764
  • 1
  • 12
  • 16
0

You've give wrong Regex match variable indexes, that's why you get weird results. Your code should look like this:

$route = new Zend_Controller_Router_Route_Regex(
'([a-zA-Z-_0-9-]+)-Widgets(?:/page/(\d+))?(?:/limit/(\d+))',
array(
    'controller'    => 'widget',
    'action'        => 'list',
),
array(
    1 => 'color',
    3 => 'page',
    5 => 'limit'
),
'%s-Widgets/'
);

$router->addRoute('color_widgets', $route);
darkerbg
  • 1
  • 1
  • I know this is old - almost as old as the code I'm working with at the moment ;) - but for anyone happening on this and unaware, I thought I'd point out the reason this isn't correct is that `(?:` begins a non-capturing group; https://stackoverflow.com/questions/3512471/what-is-a-non-capturing-group-in-regular-expressions – Andrew Dinmore Mar 05 '20 at 09:27