mxp
July 31, 2023, 1:11pm
1
I need to send the content of all children for a given page. (Because fetching all children by their own would cause an overload of the webserver.)
So I created a custom API endpoint.
'api' => [
'routes' => function () {
return [
[
'pattern' => 'custom-endpoint/(:any)',
'action' => function ($uid) {
return [
page('parent-id/' . $uid),
];
}
]
];
}
],
But the “content” response (and all other responses) are null
:
{
"content": null,
"translations": null,
"children": null,
"drafts": null,
"childrenAndDrafts": null
}
How can I access, and return, the content of all children for al given page?
mxp
August 15, 2023, 9:34am
2
@texnixe I really would appreciate a point in the right direction. Shall I provide any more information?
Not quite sure what you are doing, based on your example above, are you sure you want an API endpoint and not just a normal route like
[
'pattern' => 'custom-endpoint/(:any)',
'action' => function ($uid) {
return page('parent-id/' . $uid);
}
]
mxp
August 16, 2023, 8:23am
4
Thanks for your replay @distantnative .
I need to return the content of multiple subpages in one (API) response.
Background: Kirby is used as headless-backend. When the frontend fetches too many pages at once the server overloads. So I want to bundle the pages with many children in one response. (The above code was just the first step to get there.)
With this code I get all children listed, but again the content (and all other responses) are null
:
'api' => [
'basicAuth' => true,
'routes' => function () {
return [
[
'pattern' => 'menu/(:any)',
'action' => function ($uid) {
return [
page('PATH/' . $uid)->children()
];
}
]
];
}
],
Response is:
{
"data": {
"PATH/PAGE/SUBPAGE1": {
"content": null,
"translations": null,
"children": null,
"drafts": null,
"childrenAndDrafts": null
},
"PATH/PAGE/SUBPAGE2": {
"content": null,
"translations": null,
"children": null,
"drafts": null,
"childrenAndDrafts": null
},
[...]
}
To be honest, at first look I am not sure how the response is exactly resolved internally and why those fields and up as null and not actual data. What happens when your return page('PATH/' . $uid)->children()
directly and not wrapped in an array?
But since you were mentioning headless-backend, I was wondering if you have had a look at GitHub - getkirby/kql: Kirby's Query Language API combines the flexibility of Kirby's data structures, the power of GraphQL and the simplicity of REST. which might make your use case a lot easier.
Another way could also be Content representations | Kirby CMS for the parent page that directly returns JSON for all children.
Just thinking that this might be the easier tools to get the consumable data for your frontend.
1 Like
mxp
August 16, 2023, 10:03am
6
Oh wow, the array was actually the problem. When directly returning, like you suggested, the response is that:
{
"code": 200,
"data": [
{
"id": "PATH/PAGE/SUBPAGE1",
"num": 1,
"title": "SUBPAGE1",
"url": "http://127.0.0.1:8080/PATH/PAGE/SUBPAGE1",
"uuid": "page://xppUrW799MoOk6xN"
},
{
"id": "PATH/PAGE/SUBPAGE2",
"num": 2,
"title": "SUBPAGE2",
"url": "http://127.0.0.1:8080/PATH/PAGE/SUBPAGE1",
"uuid": "page://zEBadQ4lIUKaBx6r"
},
[...]
]
}
Is there a way do directly also get the contents of each child?
(Otherwise I would do a loop inside the action function to assemble this.)
I will also look into Content representations. Thanks!
Great, so I think now this triggers the pages collection being resolved via https://github.com/getkirby/kirby/blob/main/config/api/collections.php#L36-L40 which states that it should use the compact
view for each page. Which is defined here https://github.com/getkirby/kirby/blob/main/config/api/models/Page.php#L45-L51 and matches with what you posted.
I think you should be able to change this by sending along a query parameter in your request: view
with the value of any of the predefined views in https://github.com/getkirby/kirby/blob/main/config/api/models/Page.php or select
with a list of the fields defined in https://github.com/getkirby/kirby/blob/main/config/api/models/Page.php ,
So for example: select=title,url,content
1 Like
mxp
August 16, 2023, 11:12am
8
Awesome, that works. Thank you!
(I did not expect that query params would be forwarded to the page method.)
It’s not really that they are forwarded to the page method. It’s rather that they tell the API what to do when it encounters returning e.g. a Page
object. Since it cannot actually return an object, but needs to convert/resolve it to an array for JSON.
So our API has some defaults for our main object, how to resolve it (e.g. what parts to include in the array that represents the object). And those query params can tell the API not to go with the default but another view
or which specific fields to select
.
1 Like