Handleidingen
Wat een route teruggeeft
De standaardpagina, je eigen HTML, JSON, XML, tekst, CSV, bestanden en PDF, en hoe je elk maakt.
Elke route is een leeg canvas. Een route is een map met een index.tpl, en wat die template maakt, is het antwoord, verder niets. Nimbly voegt geen eigen layout, omhulling of formaat toe.
- Wil je de standaardpagina, met de head, de assets en inline bewerken, eindig de template dan met
[#html#]. - Wil je je eigen HTML-document, schrijf het dan.
- Wil je JSON, XML, platte tekst, CSV, een bestand of een PDF, maak dat dan.
Ze gebruiken allemaal dezelfde shortcodes, data, templates, libraries en rechten. Een site kan ze vrij combineren: een publieke site met de standaardshell, een landingspagina met een eigen document, een JSON-feed, een sitemap en een download voor alleen leden, naast elkaar.
| De route geeft terug | Hoe |
|---|---|
| De standaardpagina | [#html#] aan het eind van index.tpl |
| Je eigen HTML-document | Schrijf het document in index.tpl; zie Je eigen HTML |
| JSON | [#http-header json#] en de JSON |
| XML, een feed | [#http-header xml#] en de XML |
| Platte tekst | [#http-header txt#] en de tekst |
| CSV | [#http-header csv#] en de rijen |
| Een bestand | Een library die de headers en inhoud van het bestand stuurt |
| Een PDF | De PDF-module, vanuit een HTML-template |
| Een redirect | [#redirect url#] |
| Een statuscode | [#http-header 404#], 403 of 500 |
Het adres
Een routemap mag een punt bevatten, dus het adres kan een extensie hebben:
ext/uri/projects.json/index.tpl /projects.json
ext/uri/feed.xml/index.tpl /feed.xml
ext/uri/export/projects.csv/ /export/projects.csv
Een dynamische route werkt op dezelfde manier, bijvoorbeeld ext/uri/api/projects/(slug)/ die JSON geeft voor één project. Zie Routing.
Het contenttype
[#http-header type#] aan het begin van een template zet het Content-Type:
| Type | Content-Type |
|---|---|
json |
application/json |
xml |
application/xml; charset=UTF-8 |
txt |
text/plain; charset=UTF-8 |
csv |
application/csv; charset=UTF-8 |
css |
text/css |
js |
application/javascript |
Gebruik voor elk ander type, of voor extra headers, een library met de PHP-functie header(), zoals hieronder.
JSON
ext/uri/projects.json/index.tpl:
[#http-header json#]
[#data projects filter=published:1 sort=year|numeric|desc#]
[#fmt var=data.projects empty={} type=json#]
[#fmt ... type=json#] codeert een variabele; [#get project.title json#] codeert één waarde, met aanhalingstekens en escaping. De regeleinden tussen de shortcodes kunnen geen kwaad: JSON staat witruimte toe.
Schrijf voor een eigen vorm de JSON in de template:
[#http-header json#][#data .config.site#]{"site": [#get data.config.site.name json#], "projects": [#data-count projects#]}
Heeft het antwoord logica nodig, bouw het dan in een library:
<?php
// ext/lib/project-stats.php
function project_stats_sc($params)
{
load_library('data');
$projects = data_read('projects') ?: [];
header('Content-Type: application/json');
return json_encode([
'total' => count($projects),
'per_sector' => array_count_values(array_column($projects, 'sector')),
]);
}
ext/uri/stats.json/index.tpl bevat één regel: [#project-stats#].
XML en feeds
ext/uri/feed.xml/index.tpl:
[#http-header xml#]<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>Fieldwork projects</title>
[#data projects filter=published:1 sort=year|numeric|desc limit=20#]
[#repeat data.projects tpl=feed-item#]
</channel>
</rss>
met een template per item, ext/uri/feed.xml/feed-item.tpl:
<item>
<title>[#fmt var=item.title type=plain#]</title>
<link>[#base-url#]/projects/[#item.title_slug#]</link>
<description>[#fmt var=item.description type=plain#]</description>
</item>
Elke site antwoordt al op sitemap.xml en robots.txt. Een resource voegt zijn records toe aan de sitemap met een instelling sitemap in zijn .meta.
Platte tekst
[#http-header txt#][#data .config.site#][#get data.config.site.name#]
Projects: [#data-count projects#]
CSV
[#http-header csv#]title,sector,year
[#data projects filter=published:1#][#repeat data.projects tpl=csv-row#]
met csv-row.tpl dat één regel per record bevat. De admin exporteert ook elke resource voor gebruikers met export-<resource>.
Bestanden
Bestanden die naar de mediabibliotheek zijn geüpload, worden geleverd op /download/<uuid>, met hun opgeslagen type en naam.
Om een bestand te leveren volgens je eigen regels, zoals een document voor alleen leden of een bestand dat op verzoek wordt gemaakt, laat je een library het sturen:
<?php
// ext/lib/member-document.php
function member_document_sc($params)
{
load_library('access');
if (!access_by_feature('view-member-documents')) {
http_response_code(403);
exit();
}
$path = $GLOBALS['SYSTEM']['file_base'] . 'ext/data/.member-files/handbook.pdf';
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="Member handbook.pdf"');
header('Content-Length: ' . filesize($path));
readfile($path);
exit();
}
ext/uri/members/handbook.pdf/index.tpl bevat [#member-document#]. Met hetzelfde patroon stuur je een ZIP, een afbeelding die ter plekke wordt gemaakt of een agendabestand: de headers en de bytes zijn van jou.
PDF-documenten
De PDF-module maakt van HTML uit je eigen templates een PDF, cachet het resultaat en stuurt het als download:
./nimbly module:install pdf
load_library('pdf');
$pdf = pdf_render_cached_document([
'paper_size' => 'a4',
'orientation' => 'portrait',
'pages' => [$html],
]);
pdf_send_download($pdf, 'Project-overview.pdf');
exit();
De cachesleutel omvat het document en de renderer, dus een gewijzigde tekst of template levert vanzelf een nieuwe PDF op.
Afbeeldingen
Geüploade afbeeldingen worden geleverd op /img/<uuid>/<size>, in het formaat dat het adres vraagt en als WebP: 800w voor een breedte, 400x400c voor een uitsnede. In templates schrijft [#get-img-html#] de responsieve markup. Zie Media en inline bewerken.
Redirects en statuscodes
[#redirect [#base-url#]/en/#]
[#http-header 404#][#http-header json#]{"error": "not found"}
Een dynamische route die een request niet accepteert, valt door naar de 404-pagina van de site, die ext/uri/errors/404/ kan vervangen.
De REST API
Elke resource antwoordt ook op /api/v1/<resource> met JSON, om te tonen, lezen, maken, wijzigen en verwijderen, met de rechten van de aanroeper. Gebruik die voor apps en integraties, en schrijf eigen routes voor wat de API niet dekt. Zie de naslag van de REST API.