Continue in routes

Let’s say I have a route that looks like this:

kirby()->routes(array(
  array(
    'pattern' => '(.+)',
    'action' => function($uid) {
      if( page($uri)->pagetype() == 'blogpost' ) {
        return site()->visit($uri);
      } else {
        continue;
      }
    }
  ),
  array(
    'pattern' => 'contact',
    'action' => function($uri) {
        return site()->visit('about/' . $uri);
    }
  )
));

The first route matches anything, including contact which means the contact route will never run.

Maybe I want to run the contact route if some special condition is set. In a foreach loop I can use continue; for that. The routes are set as an array so I guess that’s not possible.

So my suggestion is that if some condition is something, be able to just skip this route and jump to the next.

Why don’t you wrap your routes within an if-else statement?

Because I don’t know the $uid before I enter the route. :confused:

I agree that something like this could be useful. continue won’t work as this is PHP syntax and can’t be used by us for this. But maybe a special return value?

Edit: Looks like filters were supposed to do that. But filterer() does not return anything. Also it makes more sense to skip routes if the filter returns false instead of stopping all-together by returning a null route. So this is a bug:

https://github.com/getkirby/toolkit/issues/211

I’ve had similar problems before with other routing frameworks - assuming the URL provides enough information on its own to decide which route to use is somewhat limiting.

If my interpretation of the filters code and what it is supposed to do (with an actual working implementation :wink:), then it seems like a reasonable solution.

Just to be very clear, this would be a route that would jump to the next, if there was a next one?

kirby()->routes(array(
  array(
    'pattern' => '(.+)',
    'action' => function($uid) {
      if( 1 == 1 ) {
        return false;
      }
    }
  )
));

Yes, but like this:

kirby()->routes(array(
  array(
    'pattern' => '(.+)',
    'action' => function($uid) {
      // won't be called if the filter returns false
    },
    'filter' => function($route) {
      if( 1 == 1 ) {
        return false;
      }
    }
  )
));

There are several things that need to be implemented for this though:

  • Support passing only one filter (the filter param expects an array of filters at the moment)
  • Support passing a filter function directly instead of the name of a previously registered filter
  • Skipping the route if the filter returns false

That’s all doable though.

1 Like

I really like that syntax, that filter is separated from action. :slight_smile:

Where does $route come from above? What does it contain? I guess I might need it inside the filter to do something? Is it required?

But except for me not knowing what $route does I agree about everything. :slight_smile:

It’s the array of the route. Useful for global filters that are used for multiple routes. You might want to store additional metadata and options in the route for that. This feature is not new but already supported.

1 Like

What I don’t get is: With the current implementation of filters, what is the intended use case for that? The filter functions just get called before the route is run, but what could you do with that?

The Panel currently uses them for auth. If the filter finds out that routes that requires auth get called, it redirects to the login page. But besides that the filters aren’t that useful at the moment.