Route placeholders in controller

Hi,

from the docs I see it is possible to add new template variables in a route’s action. If this action returns an existing page and that page has a controller is it possible to access the added template variable in the controller? Or in other words: can I pass route parameters to a controller?

Thanks in advance.

Cheers
Björn

Update: for the time being I am using the route to redirect and appending the parameter as a query string which I can access inside the controller with get().

From the docs:


return function($site, $pages, $page, $args) {

  // $args contains all arguments from the current route

};

Wow. Now that’s embarassing :grimacing:. Thanks a lot.

However, it’s not working for me. The array that should contain route arguments is empty:

c::set('routes', array(
  array(
    'pattern' => 'anfrage/(:any)',
    'action'  => function($objectId) {
      return page('anfrage');
    },
    'method' => 'GET|POST',
  ),
));

return function($site, $pages, $page, $args) {

  if (0 < count($args)) {
    $objectId = reset($args);
  } elseif (get('objectId')) {
    $objectId = get('objectId');
  } else {
    $objectId = null;
  }
 [...]
}

Am I missing something?

Update: I can access route arguments inside a controller with

$args = kirby()->route()->arguments;

but that’s a little hackish :neutral_face:

Yes. We have different ideas about what a route argument is.

The following is the code that calls kirby::render(). kirby::render() accepts a page as its first argument and then (optionally) a data array. This data array is returned by the route that you provide. In the below code, $response is what you return from your custom route.

    // work with the response
    if(is_string($response)) {
      $page = page($response);
      $this->response = static::render($page);
    } else if(is_array($response)) {
      $page = page($response[0]);
      $this->response = static::render($page, $response[1]);
    } else if(is_a($response, 'Page')) {
      $page = $response;
      $this->response = static::render($page);      
    } else if(is_a($response, 'Response')) {
      $page = null;
      $this->response = $response;
    } else {
      $page = null;
      $this->response = null;
    }

Note that if you return a page, kirby::render() is called without a data array at all, hence nothing in your controller’s $args variable. To provide additional arguments you need to return an array where the first item is the name of the page, and the second is whatever you want to provide to your controller.

For example:

c::set('routes', array(
  array(
    'pattern' => 'anfrage/(:any)',
    'action'  => function($objectId) {
      return array(
        'anfrage',
        array(
          'argument one',
          'argument two'
        )
      );
    },
    'method' => 'GET|POST',
  ),
));
2 Likes

Thanks for your detailed explanation. It’s working now as expected.