Problem with routing pattern

I’m trying to implement routing on a multilanguage site.

I’m trying to route the following structure

/en/work/type:Book+Design

to

/en/work/category/book-design

My first try was to test with a pattern that include anything after ‘work’ like

'pattern' => 'en/work/(:all)'

That pattern works for something like

en/work/name-of-post

but not for

/en/work/type:Book+Design

You can’t use parameters in your pattern. You would have to leave that out and then check for the parameter in your action. Basic example:

'pattern' => 'en/work',
'action' => function() {
  if($param = param('type')) {
     go('work/category/'.$param);
  } else {
     return page('work');
  }
  
}

You would then need a second route that reacts on the category stuff.

Thank you. I understand. Does the folder category have to be created or will Kirby create a ‘Virtual Folder’ ?

No, you don’t need the folder, but you have to create the new route and the route has to return the work page with the filtered stuff.

Ok i see clearer now :slight_smile: Thank you so much. I’ve adapted your code, works fine so far.

Could you give me an exemple for the pattern of the second route ?

i’ve created the second route for my setup. How can i pass data to my controller for the work page to filter the output ?

			[
				'pattern' => 'en/work',
				'action' => function() {
					if($param = param('type')) {
						$param = strtolower($param);
						$param = str_replace('+', '-', $param);
  						go('en/work/category/' . $param);
					} else {
                        return page('work');
					}
				}
			],
			[
				'pattern' => 'en/work/category/(:all)',
				'action' => function() {
					return page('work');
				}
			]

The data from the route is automatically passed to the controller, you can fetch it with $kirby->route()->arguments()

https://getkirby.com/docs/guide/templates/controllers#arguments-from-the-router

Ok. I get the arguments in my controller.
How can i check for a specific one ?

isset($args['type'])

seems not to work.

The array should contain all values from your (:all) placeholder. Or are you referring to the first route?

Check with dump(kirby->route()->arguments()) what your arguments array contains.

Thank you.

That’s what i did and now it works so far. My next step will be to make this router work in a multilanguage setup.

any idea why using dump i get two identical arrays ?

Array ( [0] => book+design )
Array ( [0] => book+design )

Pure magic :slightly_smiling_face: No, I have no idea.

I’d use (:any) instead of (:all) as placeholder in the route.

I’m using (:any) by now.

I’m not sure where that double arrays came from but i’ve tried to break them down to a String which gives my the formatting Book+Design wich i can then use to filter work types. It seems a bit complicated but i dont see any other solution for now.

        // get arguments from the router
        if($args = $kirby->route()->arguments()) {
            $args = array_shift( $args );
            $args = str_replace('-', '+', ucwords($args, '-'));
            $work = $work->filterBy('type', $args, ',');
        }

It’s a bit weird that you get two arrays where there should be only one. Use 'var_dumpinstead ofdump` to check where these values come from.

when using var_dump instead of dump() the output seems to be ok

array(1) { [0]=> string(16) "book-design" }

Ok, then you can leave that array_shift part out.

Yes, but i have to use implode because ucwords needs a string as an input.

$args = implode('', $args);
$args = str_replace('-', '+', ucwords($args, '-'));

which generates Book+Desing as intended. Then i filter with

$work = $work->filterBy('type', $args, ',');

which should return type:Book+Desing posts but with no result so far.

So “Book+Design” is what is literally stored in your content files?