@jevets: Yes, stumbled upon the quotes by mistake – already corrected. Unfortunately it doesn’t fix it for me. At least the route seems to work now as it doesn’t load the Error-template anymore, but I still get an Internal Server Error upon accessing http://localhost:3000/api/v1/blog in the browser or when trying to log it to the console.
I think the reason page('blog') works and pages()->find('blog') doesn’t is because these routes are loaded before pages() (or $pages) have been populated with an index of all the site’s pages.
@rppld Are you running this from a javascript file or directly in the browser’s console?
By the way, there’s also collection::toArray and collection::toJson
response::json() should convert whatever data is passed to it to json automatically.
I’ve found doing this can be more explicit and easier to figure out in the future, when working with collections of pages (instead of a single page object):
// in the route
'action' => function() {
// get the article pages
$articles = page('blog')->children()->visible();
$data = [];
// Transform for API delivery
foreach ($articles as $article)
{
$data[] = $article->serialize();
}
// Now you're sending a plain old array to `response::json()`
return response::json($data);
}
I’ve found that when using kirby()->routes() in this way from a plugin, there’s no way to specify route filters.
The alternative way to setup routes is instantiate a router yourself, something like this:
$router = new \Router();
$router->filter( /* ... */ );
$router->route( /* ... */ );
// But then you'll have to run the router and exit,
// which isn't quite as nice-looking in my opinion
@lukasbestle Do you happen to know of any way to add route filters to kirby() from plugins?
Nope, unfortunately that won’t work. The router itself is started after the plugins have been loaded, kirby()->routes() only adds the routes to an array that is used to initialize the router with.
Is there any way to add route filters to kirby’s router (after plugins are loaded)? Or must one create his own Router instance to use user-defined route filters?
Generally that would be kirby()->router()->filter( /* ... */ );, but as the router is run immediately after it is created, the filters won’t apply at all, no matter when adding the filter.
I recommend using your own router. That makes you completely independent from the built-in router and is not that much more code.
For future reference on the topic, you’ll probably eventually need to filter your routes, i.e. to make sure a user is logged in or to make sure the user has permission to access the resource. You can’t add filters when using kirby()->routes() in a plugin, but you can instantiate your own router.
In plugins, do this instead of using kirby()->routes():
instantiate your own router
register your filters and routes
run your router
(This code is untested but should be enough to get you going)
// 1. Instantiate your own router
$router = new \Router();
// 2. Register your filters and routes
// filters
$router->filter('auth', function() {
if (!site()->user()) go('login');
});
$router->filter('guest', function() {
if (site()->user()) go('dashboard');
});
// routes
$router->register('login', [
'method' => 'GET|POST',
// this will redirect the user if she's already logged in
'filter' => 'guest',
'action' => function() {
// GET shows a login form
// POST attempts to log in the user
}
]);
$router->register('logout', [
'filter' => 'auth',
'action' => function() {
if (site()->user()) site()->user()->logout();
go('login');
}
]);
$router->register('dashboard', [
'filter' => 'auth',
'action' => function() {
// show the logged-in user his dashboard
}
]);
// 3. Run your router
$route = $router->run( kirby()->path() );
if (! is_null($route)) {
die( call($route->action(), $route->arguments()) );
}
``
Could you explain how the code below relates to the article.php, it doesn’t seem to be effecting it
'action' => function() {
// get the article pages
$articles = page('blog')->children()->visible();
$data = [];
// Transform for API delivery
foreach ($articles as $article)
{
$data[] = $article->serialize();
}
// Now you're sending a plain old array to `response::json()`
return response::json($data);
}
I came across this post a couple of months ago because I obviously had some similar requirements. I found the various responses here very helpful but I figured that there should be a plugin that somewhat simplifies and standardizes the process of creating custom APIs. So I built one.
In case anybody else is interested - which, judging from the conversation some of you might be;
But there’s one question left for me. Maybe you’ve got an idea for this…
The output of the markdown is pure text. Is there a solution to output interpreted html code for the text field, or is it more wise to interpret it via the javascript?
e.g. i’ve got this output:
{
"id":"content",
"url":"http:\/\/kickstarter.kirby\/api\/content",
"uid":"content",
"title":"content",
"text":"hi **how** is it?\n\n# this is a headline\n## this is a smaller subline\n\n(image: gallery_01.jpg)\n\n****"
}