Apologies to revive this old post, but it came the closest to my problem and I might have found a solution or add a missing link.
My situation is that I created a plugin to handle multiple API calls to different endpoints
example.com/v1/customerX/locations
example.com/v1/customerX/locations/1
example.com/v1/customerX/locations/2
example.com/v1/customerY/locations
example.com/v1/customerY/locations/5
example.com/v1/customerX/news{/:id}
example.com/v1/customerX/events{/:id}
For Kirby I setup a content folder:
content/
customerX/site.txt
customerY/site.txt
And my goal is to reuse the API endpoints and integrate them in kirby and be able to query all those virtual kirby pages like native pages.
my plugin index.php looks like this: (Work in Progress!)
load([
'EntriesPage' => 'src/EntriesPage.php',
'EntryPage' => 'src/EntryPage.php',
], __DIR__);
Kirby::plugin('mo/core', [
'routes' => function($kirby) {
return [
[
'pattern' => [
'(:any)/locations' // needs more patterns?!
],
'language' => '*',
'action' => function ($language, $parent) {
$page = [
'slug' => 'locations',
'template' => 'locations',
'num' => 0,
'model' => 'entries',
'parent' => page($parent),
'children' => [],
'content' => [
'title' => t('Standorte', 'Standorte'),
]
];
$page = new EntriesPage($page);
return $page;
},
],
];
},
'pageModels' => [
'entries' => 'EntriesPage',
'entry' => 'EntryPage',
],
]);
The EntriesPage
Model creates the children()
class EntriesPage extends EntryPage
{
public function children() : Pages
{
// Query the `record` collection, could also be `geojson`
$results = $this->_query('records/'. $this->slug());
foreach(A::get($results,'records') as $item) {
$pages[] = [
'slug' => $item['id'],
'num' => 0,
'parent' => $this,
'model' => 'entry',
'template' => 'location',
'content' => array_merge($item,[
'title' => t($item['name_en'], $item['name'])
])
];
}
return Pages::factory($pages, $this);
}
}
And EntryPage Model has a method to query the API.
So this works fine if I visit, mykirby.com/customerX/locations
but if I want to show a list of locations as teaser on the parent parent page mykirby.com/customerX
and try to access the location children with
page('customerX/locations')
, the children aren’t registered with kirby, as @bvdputte described it initially.
@texnixe is correct when she says, VP are getting registered in the guide “Virtual Pages from a Database”.
In the Database example it comes down to creating a file in the content folder.
So when I added a locations/entries.txt to each customer:
content/
customerX/site.txt
locations/entries.txt
customerY/site.txt
then customerX/locations
wasn’t a virtual file anymore, and it showed up in the index with all the children. But I don’t want to add a bunch of ghost folders/files to my content, just to trick Kirby.
It comes down to Pages::inventory()
that collects all files (children, images, templates) and sets the $page->children()
somewhere in \HasChildren->index()
when you attempt to find a page(’…’)
So my solution is to overwrite inventory
in the site
model like this:
/site/models/site.php
class SitePage extends Page
{
public function inventory(): array
{
if ($this->inventory !== null) {
return $this->inventory;
}
$kirby = $this->kirby();
$this->inventory = Dir::inventory(
$this->root(),
$kirby->contentExtension(),
$kirby->contentIgnore(),
$kirby->multilang()
);
// register my virtual Parent Page
$this->inventory['children'][] = [
'dirname' => "locations",
'model' => 'entries',
'num' => 0,
'root' => "M:\WEB\project\content\customerX/locations", //?
'slug' => "locations",
];
return $this->inventory;
}
}
And now everything works as expected.
I still have to make it more universal for my case and experiment with the virtual inventory, but this did the trick to register a virtual page with child pages.
Hopefully all of this makes sense, and maybe it helps someone find a solution.
@bvdputte recommended his plugin to me GitHub - bvdputte/kirby-vpkit: Virtual pages helper for multilingual Kirby 3 that deals with virtual pages. It’s a different approach, and worth to explore.
Any insight into how or why inventory() plays such an important role is appreciated. I just came to this conclusion by a lot trial and error and stepping through the code with Xdebug.