Guias
O que uma rota devolve
A página padrão, seu próprio HTML, JSON, XML, texto, CSV, arquivos e PDF, e como fazer cada um.
Cada rota é uma tela em branco. Uma rota é uma pasta com um index.tpl, e o que esse template produz é a resposta, nada mais. O Nimbly não acrescenta layout, invólucro ou formato próprio.
- Para ter a página padrão, com o head, os assets e a edição na página, termine o template com
[#html#]. - Para ter seu próprio documento HTML, escreva-o.
- Para ter JSON, XML, texto simples, CSV, um arquivo ou um PDF, produza isso.
Todos usam os mesmos shortcodes, dados, templates, bibliotecas e permissões. Um site pode misturá-los à vontade: um site público com a shell padrão, uma landing page com documento próprio, um feed JSON, um sitemap e um download só para membros, lado a lado.
| A rota devolve | Como |
|---|---|
| A página padrão | [#html#] no final do index.tpl |
| Seu próprio documento HTML | Escreva o documento no index.tpl; veja Seu próprio HTML |
| JSON | [#http-header json#] e o JSON |
| XML, um feed | [#http-header xml#] e o XML |
| Texto simples | [#http-header txt#] e o texto |
| CSV | [#http-header csv#] e as linhas |
| Um arquivo | Uma biblioteca que envia os cabeçalhos e o conteúdo do arquivo |
| Um PDF | O módulo de PDF, a partir de um template HTML |
| Um redirecionamento | [#redirect url#] |
| Um código de status | [#http-header 404#], 403 ou 500 |
O endereço
Uma pasta de rota pode conter um ponto, então o endereço pode ter uma extensão:
ext/uri/projects.json/index.tpl /projects.json
ext/uri/feed.xml/index.tpl /feed.xml
ext/uri/export/projects.csv/ /export/projects.csv
Uma rota dinâmica funciona do mesmo jeito, por exemplo ext/uri/api/projects/(slug)/, que responde JSON para um projeto. Veja Roteamento.
O tipo de conteúdo
[#http-header type#] no início de um template define o Content-Type:
| Tipo | 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 |
Para qualquer outro tipo, ou para cabeçalhos extras, use uma biblioteca com a função header() do PHP, como mostrado abaixo.
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#] codifica uma variável; [#get project.title json#] codifica um único valor, com aspas e escape. As quebras de linha entre os shortcodes não fazem mal: o JSON permite espaços em branco.
Para um formato próprio, escreva-o no template:
[#http-header json#][#data .config.site#]{"site": [#get data.config.site.name json#], "projects": [#data-count projects#]}
Quando a resposta precisa de lógica, monte-a numa biblioteca:
<?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 tem uma linha: [#project-stats#].
XML e 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>
com um template por 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>
Todo site já responde sitemap.xml e robots.txt. Um recurso acrescenta seus registros ao sitemap com uma configuração sitemap no seu .meta.
Texto simples
[#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#]
com csv-row.tpl contendo uma linha por registro. O admin também exporta qualquer recurso para usuários com export-<resource>.
Arquivos
Os arquivos enviados à biblioteca de mídia são servidos em /download/<uuid>, com o tipo e o nome guardados.
Para servir um arquivo com suas próprias regras, como um documento só para membros ou um arquivo gerado na hora, deixe uma biblioteca enviá-lo:
<?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 contém [#member-document#]. O mesmo padrão envia um ZIP, uma imagem gerada na hora ou um arquivo de calendário: os cabeçalhos e os bytes são seus.
Documentos PDF
O módulo de PDF transforma em PDF o HTML dos seus próprios templates, guarda o resultado em cache e o envia como 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();
A chave do cache cobre o documento e o renderizador, então um texto ou template alterado gera um novo PDF sozinho.
Imagens
As imagens enviadas são servidas em /img/<uuid>/<size>, no tamanho que o endereço pede e em WebP: 800w para uma largura, 400x400c para um recorte. Nos templates, [#get-img-html#] escreve o markup responsivo. Veja Mídia e edição inline.
Redirecionamentos e códigos de status
[#redirect [#base-url#]/en/#]
[#http-header 404#][#http-header json#]{"error": "not found"}
Uma rota dinâmica que não aceita uma requisição cai na página 404 do site, que ext/uri/errors/404/ pode substituir.
A API REST
Todo recurso também responde em /api/v1/<resource> com JSON, para listar, ler, criar, alterar e excluir, com as permissões de quem chama. Use-a para apps e integrações, e escreva rotas próprias para o que ela não cobre. Veja a referência da API REST.