Problem with routing pattern


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

I’m trying to route the following structure




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


but not for



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')) {
  } 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()


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


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?