Content from an API
Enrich your site with content fetched from any API
For this example, we use a freely accessible API, in this case the New York Times Movie Review API. To follow this example, create an account and an example app by following the instructions.
First, create a parent page, e.g. reviews
in the /content
folder and inside it, a reviews.txt
text file.
Title: Movie reviews
----
Intro: This page lists all available movie reviews from the NYT movie review API.
This page will serve as our model for child pages.
The page model
In the Reviews
page model, we redefine the children()
method to get the subpages from the API instead of from the file system:
<?php
use Kirby\Uuid\Uuid;
class ReviewsPage extends Page
{
public function children(): Pages
{
if ($this->children instanceof Pages) {
return $this->children;
}
$results = [];
$pages = [];
$apiKey = 'put-your-api-key-here';
$request = Remote::get('https://api.nytimes.com/svc/movies/v2/reviews/picks.json?api-key=' . $apiKey);
if ($request->code() === 200) {
$results = $request->json(false)->results;
}
foreach ($results as $key => $review) {
$pages[] = [
'slug' => Str::slug($review->display_title),
'num' => $key+1,
'template' => 'review',
'model' => 'review',
'content' => [
'title' => $review->display_title,
'headline' => $review->headline,
'byline' => $review->byline,
'summary' => $review->summary_short,
'date' => $review->publication_date,
'link' => $review->link->url,
'linkText' => $review->link->suggested_link_text,
'cover' => $review->multimedia->src,
'uuid' => Uuid::generate(),
]
];
}
return $this->children = Pages::factory($pages, $this);
}
}
Replace api-key
with the API key you got for your app.
Unless you have disabled UUIDs in your config, you have to pass a uuid
field in the content array to prevent Kirby from generating the page in the file system when the $page->uuid()
method is called.
If you generate the UUIDs automatically like in the example above, they will change at every load. However, if you want to reference your virtual pages anywhere with their UUID, make sure to use a unique string that does not change.
Using the Remote::get()
method, you connect to the API and fetch the results. Within the foreach loop, you feed the results into the $pages
array and finally pass it all to the Pages::factory()
method.
The overview template
The pages are now accessible in the template and you can loop through them like through a normal set of Kirby pages, using the fields defined in the content
array:
<?php snippet('header') ?>
<main>
<header>
<h1><?= $page->title() ?></h1>
</header>
<ul>
<?php foreach ($page->children() as $review): ?>
<li>
<h2><?= $review->title() ?></h2>
<a href="<?= $review->url() ?>">Read review summary</a>
</li>
<?php endforeach ?>
</ul>
</main>
<?php snippet('footer') ?>
The child page template
For the children themselves, you can create their own review.php
template to access more details:
<?php snippet('header') ?>
<main>
<article class="review">
<header>
<h1><?= $page->title() ?></h1>
<time><?= $page->date()->toDate('d F Y') ?></time>
</header>
<h2><?= $page->headline() ?></h2>
<p>by <?= $page->byline() ?></p>
<?= $page->summary() ?>
<?php if ($page->cover()->isNotEmpty()): ?>
<img src="<?= $page->cover() ?>" alt="">
<?php endif ?>
</article>
</main>
<?php snippet('footer') ?>
The result
The result could then look something like this:
