How forms are read
This page covers how Ghostwriter reads each resource's form: which fields it writes, the field macros, Builder and Repeater support, and house style.
Filament forms are PHP, not data, so Ghostwriter reads each resource's form by building it the way its Create page would (or its Edit page, for a resource that can't create). It reduces every field to a kind, then stores the result, the form map, in the ghostwriter_form_maps table.
When forms are read
A form is read the first time Ghostwriter needs it, and what it read is kept. After changing a form, read it again:
php artisan ghostwriter:scan
or Read the forms again in Get started. Add the command to your deploy script so the maps keep up with the code. If a form has changed since it was last read, the Overview says so, because kinds learned from the old form may need learning again.
Field kinds
| Kind | Fields | The writer produces |
|---|---|---|
| text | TextInput |
plain text, within maxLength |
| number | TextInput::numeric() |
a number |
| long text | Textarea |
plain text, within maxLength |
| rich text | RichEditor (HTML or JSON), MarkdownEditor |
markdown, stored in the field's own format |
| choice | Select, Radio, ToggleButtons |
one of the field's options |
| choices | Select::multiple(), CheckboxList, ToggleButtons::multiple() |
several of the options |
| toggle | Toggle, Checkbox |
on or off |
| blocks | Builder |
a list of blocks, each with its own fields |
| rows | Repeater |
rows sharing the same fields |
| left for a person | FileUpload, DatePicker, ColorPicker, relationships (Select or CheckboxList with relationship(), Repeater::relationship()), and any other field |
nothing; left as it is, or filled from the house style |
Fields inside layout components (Section, Tabs, Grid, Fieldset, Group and the like) are read wherever they are. Builder blocks and Repeater rows are read up to six levels deep. A Builder or Repeater with nothing writable in it is left for a person.
What the writer is told about each field:
- its label, and whether it's required
- its helper text, and any
ghostwriterHint()(see below) - for choices, the options
- for text, the maximum length
Fields that are hidden or only shown under a condition are read too, so the writer knows about them.
Telling Ghostwriter about a field
Two macros, available on every field:
Leaving a field out
TextInput::make('seo_title')->ghostwriter(false)
Ghostwriter won't write to this field, and leaves it for a person. On an upload field it also hides the image button.
Adding a hint
Textarea::make('summary')->ghostwriterHint('Two sentences, for listings. No full stop at the end.')
The hint is given to the writer alongside the field's helper text. It's useful when the helper text is written for editors and the writer needs something more specific.
Alt text for photos
FileUpload::make('image')->image()->ghostwriterAlt('image_alt'),
TextInput::make('image_alt')->label('Alt text')->ghostwriter(false),
ghostwriterAlt() names the field beside a single-image upload that holds its alt text. When a photo is chosen with the image button, Ghostwriter fills it with the photo library's description of the photo.
Fields that can't be read
If building part of a form throws an exception (for example, a field whose options query needs a record that doesn't exist yet), Ghostwriter skips that part and records the problem. Problems are shown in Get started and on the Overview. The rest of the form is still written.
A field Ghostwriter doesn't know, such as a custom field or one from a plugin, is read as left for a person.
House style
Ghostwriter learns how a resource's published records are really built, not just what the form allows:
- Which blocks are used, and in what order, so a draft's Builder content follows the same pattern.
- Settings the records agree on. A block setting, toggle or choice that the records almost always set the same way (a spacer's height in each position, a text block's width) is copied into the draft.
- Values that refer to the record itself. A link or setting that points at the record it's on becomes the new record's.
- Settings that differ from record to record are left alone, and listed in the notification after Use this draft as still to set by hand.
The writer only writes words. Everything else comes from your own records, so a draft looks like it belongs.