Routes: return template to fake a page - running into error

Hi guys,

for a plugin, I am trying to set up routes for non existing pages that return templates located within the plugin:

$kirby->set('route', [
  'pattern' => $passport->url() . '/(trip|home)/(:num)',
  'action'  => function($type, $id) {
    ...

    return \tpl::load(kirby()->registry->get('template', 'passport-trip'), ['trip' => $trip]);
  }
]);

However I get the following error:

Catchable fatal error: Argument 1 passed to Kirby::render() must be an instance of Page, boolean given, called in /Users/nhoffmann/Development/passport/kirby/kirby/component/response.php on line 25 and defined in /Users/nhoffmann/Development/passport/kirby/kirby.php on line 558

I know that the template is found and loaded correctly, cause when I omit passing through $trip, I see half of the template until the error that $trip cannot be found.

I cannot wrap my brain around the error. Any ideas, previous experiences, solutions from anyone?

p.s. and yes I really would not like to put page placeholder into the content folder as this would make the plugin install more complicated

When return don’t you need to return a site()->visit? Can you use echo instead of return?

1 Like

What actually did work is to echo it and then just return false.
It is quite the hack, I guess, and I will see what other problems I will run into with it.

So if anyone has a smoother idea for pages without content files, let me know.

Kirby expects a Response for route actions:

An action must either return a page object, a response object, redirect to a different URL or exit the code execution by returning false.
https://getkirby.com/docs/developer-guide/advanced/routing

The logic is a bit more precise if you look at the Kirby\Component\Response class, which handles the “hey, we want to make a response out of this mixed input” use case. If you return a string, it will treat it as a page uri:

if(is_string($response)) {
  return $this->kirby->render(page($response));
}

That’s probably a bad case of tight coupling between this class and a behavior that some Kirby helpers and/or internals expected. ^^ (A more agnostic class would return new Response($response) in that situation.)

Anyway, the clean way to return a HTML response from a route action when the action itself provides the full HTML result would be:

function(…) {
  $html = ...;
  return new Response($html);
}

You can also handle different HTTP statuses, with e.g; return new Response($html, 'html', 404);

4 Likes

Thanks a lot, completely overlook that. Returning with Response works like a charm.