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.