Hi,
I would like to use a route filter on pages with a certain template that, when that page is invisible, only shows the page when the user is logged in (some basic authentication which avoids direct access for âanonymous usersâ to invisible pages). But I canât get it to work.
I assume I cannot use filters on the âdefault methodâ via c::set('routes',...)
? Is this correct?
So I tried the âuse a custom routerâ way. But I canât seem to get it to work. This is in my config.php
$router = new Router();
$router->register(array(
array(
'pattern' => 'test',
'method' => 'GET',
'action' => function() {
error_log("test");
}
)
));
When I visit the test
page I am redirected (via 302 redirect) to the home page and nothing shows up in my error log.
Any tips on what I am doing wrong?
PS: Iâve read
and Iâm using Kirby 2.5.4
Thx!
I think the code has to go into a plugin file. Also, you have to run the router:
<?php
$router = new Router();
$router->register(array(
array(
'pattern' => 'test',
'method' => 'GET',
'action' => function() {
go('/');
}
)
));
if($route = $router->run()) {
$response = call($route->action(), $route->arguments());
}
1 Like
Hi @texnixe, putting it in a plugin file is a must indeed (it doesnât run from config.php) AND you have to run it.
What does this do: if($route = $router->run())
?
Also; I noticed that I cannot return json from a custom router. Is this expected behaviour?
return response::json(json_encode($data));
works perfectly when added via c::set("routes")
, but not when copied into a new router instance. I am getting redirected to the home page again. The 'action'
set in the custom router is ran though, as Iâve logged it.
According to the code comments it âiterates through every route to find a matching routeâ.
Thanks. Have you seen:
Also; I noticed that I cannot return json from a custom router. Is this expected behaviour?
return response::json(json_encode($data)); works perfectly when added via c::set(âroutesâ), but not when copied into a new router instance. I am getting redirected to the home page again. The âactionâ set in the custom router is ran though, as Iâve logged it.
Or should I use a route which returns json exclusively in c::set("routes")
, but that canât have filters then?
Yes, Iâve seen it but I have no answer, Iâm afraid. I wonder if we really have to run a new router instance to be able to use filters, or if it isnât possible using kirby()->routes()
in a plugin file.
It seems like the âdefaultâ kirby router doesnât support filtering, and the custom router doesnât support to return json. This feels un-kirby to me
I hope a solution comes soon for this inconsistency - pretty please.
Custom routers do indeed support JSON responses:
$router = new Router();
$router->register(array(
array(
'pattern' => 'test',
'method' => 'GET',
'action' => function() {
return response::json(['this' => ['is', 'a', 'test']]);
}
)
));
if($route = $router->run()) {
$response = call($route->action(), $route->arguments());
die($response);
}
Tested with Kirby 2.5.5-RC1.
You can also use filters with the c::set('routes')
approach, just not âglobalâ filters. But adding a filter
callback to the route array should definitely work.
Hi @lukasbestle, this indeed seems to work with JSON (on Kirby 2.5.4). But, then again, I have another route registered in the same router that should return a page (not JSON), and then your code doesnât work for that scenario for me?
Am I doing something wrong?
Code:
$router = new Router();
$router->register(array(
array(
'pattern' => [
'(:any)/news',
'(:any)/news/(:any)'
],
'method' => 'GET',
'filter' => 'auth',
'action' => function($lang) {}
),
array(
'pattern' => 'test',
'method' => 'GET',
'action' => function() {
return response::json(['this' => ['is', 'a', 'test']]);
}
)
));
if($route = $router->run()) {
$response = call($route->action(), $route->arguments());
die($response);
}
FYI: The first route works as expected when I remove die($response);
from your code.
â Edit:
I read up here, and now I understand why the first works without die()
-> it runs the filter and then the default Kirby CMS router takes over and does what it usually does because the action is empty. Right?
If so, is there any way to call the default router in the action of the first route to avoid die();
?
â Edit 2:
After thinking a bit further about it; in my scenario it wouldnât make sense to use a custom router for this as I can do it all in the regular routes. (I thought I couldnât use alternative methods nor filters in the regular kirby routes â which is obviously wrong as shown here)
I actually donât see a scenario for using a custom router then? Is there?
Well, custom routers were originally meant to be used outside of the CMS (when using the Toolkit in completely custom projects that donât involve the core). But many people use custom routers in plugins to have a bit more control over them.
The issue with your example is that you donât have an auth
filter defined in your custom router. And of course your empty action
function doesnât make sense as die($response)
expects some kind of response string or object (otherwise itâs basically die(null)
).
Edit: I read your question again and now understand what you mean: Custom routers donât make sense at all if you want to âfall throughâ to the Kirby router in specific situations. They only make sense if you want to fall through to the Kirby router if no one of your custom routes matches, not in any other situation.
1 Like