bdereta
bdereta

Reputation: 913

Setting up conditional routing in CakePHP

I'm using CakePHP 2.7 and I have following routes defined in app/Config/routes.php:

Router::connect('/:state/:location/:slug',
    ['controller' => 'pages', 'action' => 'display_program'],
    ['pass'=> ['state', 'location', 'slug']]
);
Router::connect('/:state/:location/:degree_level/:slug',
    ['controller' => 'pages', 'action' => 'display_program'],
    ['pass'=> ['state', 'location', 'degree_level', 'slug']]
);
Router::connect('/:state/:location/:degree_level',
    ['controller' => 'pages', 'action' => 'list_programs'],
    ['pass'=> ['state', 'location', 'degree_level']]
);

The problem that I'm encountering is when I'm passing three values, the third value can either be degree level or a slug.

/az/campus/program-name-slug [should route to pages->display_program()]

/az/campus/masters/program-name-slug [should route to pages->display_program()]

/az/campus/masters [should route to pages->list_programs()]

Right now all three urls route to display_program() action however I need the third one (without the slug) to route to list_program(). Any ideas much appreciated!

Upvotes: 2

Views: 676

Answers (1)

ndm
ndm

Reputation: 60463

So if your degree levels never conflict with the program names, then you can use a simple regex to further narrow down what the degree_level element matches, something like

Router::connect('/:state/:location/:degree_level',
    ['controller' => 'pages', 'action' => 'list_programs'],
    [
        'pass'=> ['state', 'location', 'degree_level'],
        'degree_level' => 'undergraduate|graduate|bridge|doctorate'
    ]
);

That way the degree_level element will only match in case one of four given strings is used.

In order for this to finally work you must put this route before the route with the slug element, otherwise the slug one will steal the route, as it greedily matches any string, ie finally you should have the routes ordered like

// specific count match, semi-specific value match
Router::connect('/:state/:location/:degree_level',
    // ...
);

// specific count match, greedy value match
Router::connect('/:state/:location/:slug',
    // ...
);

// sepcific count match, greedy value match
Router::connect('/:state/:location/:degree_level/:slug',
    // ...
);

See also Cookbook > Routing > Route Elements

Upvotes: 2

Related Questions