Fields
Field definitions, field types, and reading fields in templates and PHP.
On this page
Fields and field types
A field (site/fields/{name}/_index.json) is a named, reusable definition: a label, a type and default options. A field type is the PHP class that gives a type its decode, encode and validate behaviour. A field picks a type; a type has no name of its own.
A bare name is your site's own: body is site/fields/body. A type the core ships carries the core's alias: @phlat/markdown is the core's markdown type. Nothing falls back from one to the other, so your site uses a core field or type only by naming it.
// site/fields/body/_index.json
{
"label": "Body",
"type": "@phlat/markdown",
"options": { "required": false }
}
Declaring fields for a view
A view's _index.json lists the fields it uses under fields, keyed by the name the value is stored under. An entry with nothing else names your field of that name, and its keys override that field's options for this view. An entry with a type declares the field right there:
// site/views/post/_index.json
{
"fields": {
"title": { "required": true, "max_length": 40 },
"body": {},
"accent": { "type": "@phlat/color", "label": "Accent" }
}
}
Reading fields
Any property of a page that isn't built in resolves against _data.json and returns a FieldValue:
{$page->title} {* decoded string *}
{$page->body|render} {* via the field type's render template *}
{if !$page->cover->empty()}
<img src="{$page->cover}">
{/if}
A FieldValue is always truthy in PHP, so check ->empty() before rendering optional fields.
$field = $page->body; // FieldValue
$raw = $field->value; // raw stored value
$out = $field->decode(); // decoded value (HTML for markdown, etc.)
$empty = $field->empty();
A code field can use a different Phiki theme per render with ->highlight($theme), or a default theme set on the field definition:
{$page->code->highlight($codeTheme)|noescape}
{* site/views/post/_index.json *}
"code": { "theme": "nord" }
Built-in field types
Outside the core's own files these are named with the core's alias: @phlat/text, @phlat/markdown.
| Type | Description |
|---|---|
text |
Plain string |
markdown |
Markdown source rendered to HTML via CommonMark |
code |
Source code, syntax-highlighted with Phiki and rendered as a complete <pre> element. Stored as {language, code}. ->highlight($theme) picks the theme per render |
image |
Image file reference, decodes to a PageImage (see Images) |
datetime |
ISO 8601 timestamp |
richtext |
HTML content, passed through unescaped |
repeater |
An ordered list of same-shape rows |
number |
Int or float, null if unset |
boolean |
True or false; an unchecked checkbox encodes to false |
select |
A string chosen from the declared options |
checkboxes |
Any subset of the declared options (a list, or a map of value to label), stored as a JSON list |
list |
A JSON array of strings, decodes to a PHP array |
object |
A JSON object, keys read as properties |
url |
An external URL, validated with San::url() |
color |
A hex color, #rgb normalized to #rrggbb |
password |
A hashed password, always blank on decode |
file |
A file stored on the page, decodes to a PageFile |
relation |
A UUID reference to another page, decodes to a Page |
datafile |
A companion JSON data file in the same directory |
blocks |
An ordered list of typed blocks, each a named group of sub-fields |
stack |
An ordered list where each entry references one global field by name |
collection |
Structured items kept in a database of their own, queried with the same syntax as find() |
Repeaters
A repeater stores an ordered list of rows that share one shape, inline in _data.json. The shape is declared under options.fields, naming other fields:
// site/fields/nav/_index.json
{
"label": "Navigation",
"type": "@phlat/repeater",
"options": {
"fields": { "label": [], "href": [] }
}
}
Each row decodes to a mini page, so sub-fields read like page fields:
{foreach $page->nav->decode() as $item}
<a href="{$item->href}">{$item->label}</a>
{/foreach}
For rows of several shapes use blocks.
When you need more
To extend a field definition or write your own field type, see Custom fields.