Step-by-step workflows
Admin steps assume you can open the Filament panel and see System → Custom Fields. Developer steps assume the plugin is registered as in the usage guide.
Create a custom field (admin)
- Sign in to the Filament panel (starter path:
/admin). - Open Custom Fields in the System group.
- Click Create.
- Choose Target Model from discovered Eloquent models (default scan:
app/Models). Example:User (App\Models\User). - Set Internal Name — snake_case, letters/numbers/dashes/underscores only, unique per model. This is the storage and code key (
first_name,skills). - Set the human Label shown on forms and tables.
- Pick a Field Type. Extra sections appear for textarea, multi-select/tags, file, and option lists. See Features.
- Toggle Required if the host form must not submit empty.
- Optional: Sort order (lower first), Laravel Validation Rules as tags (
max:255,email), Hint, Placeholder, Group (for seeders/layout), and conditional visibility fields. - Save. You are redirected to the list, not the edit page.
Nothing appears on Users yet?
The host User resource must include
CustomFieldMapper::makeFormFields(User::class). The starter already does. Other models need that one-time developer step.
Options, clone, and ordering
- For Select, Radio, Multi-select, or Tags, expand Options.
- Add rows with Label and Value. Collapsed rows show the option label (or value if the label is empty). Drag to reorder.
- For Tags, optionally pick a Badge color. Empty = auto from the theme palette.
- On the list, Clone is a Pro action (Core shows Clone · PRO). With Pro it duplicates a field (name becomes
{name}_copy). - Filters: target model and type. Default sort is
sort_order.
Add fields to a Filament resource (developer)
- Add
HasCustomFieldsto the Eloquent model. File fields are Pro: addHasMedia+HasCustomFieldMediaonly when Pro is installed. - Put
custom_fieldson fillable (or sync in a hook). - In the resource form schema, spread mapper components into a Section.
- On the table,
modifyQueryUsing(fn ($q) => $q->withCustomFields())and spreadmakeTableColumns. - On a view page, use
makeInfolistEntries. - Create a Custom Field targeting that model class. Open Create/Edit on the resource — the new input is there, in sort order.
Starter reference: app/Filament/Resources/Users/Schemas/UserForm.php and UsersTable.php.
Capture, validate, and store
- Open a User (or your model) Create/Edit page in Filament.
- Fill account fields and the Custom Profile Data section.
- Built-in type validation runs (email, url, numeric, required). Extra rule tags from the definition also run.
- Save the record. Non-file values write to
custom_field_values. Files attach to the model’s media collection; metadata is synced automatically. - Re-open the record: values hydrate from EAV / media, not from a JSON column on
users.
Conditional fields (Pro) only show when another custom field’s current value matches Visible when value.
Present data
- Table: toggleable columns; booleans as icons; tags/multi-select as colored badges; image files as Spatie image columns when marked image-only/editor.
- Infolist: same casting; rich textarea shown as HTML; placeholder “—” when empty.
- API / JSON: if
append_to_jsonis true, each model includes acustom_fieldsobject keyed by internal name.
Seed a realistic User profile set
php artisan dynamic-fields:seed-user-fields
php artisan dynamic-fields:verify
Use --fresh on the seed command only when you intend to delete existing fields for that model. dynamic-fields:seed-extended-fields is Pro (multi-select, tags, files, rich textarea).
Move definitions between environments
php artisan dynamic-fields:export --path=storage/app/custom-fields-export.json
php artisan dynamic-fields:import storage/app/custom-fields-export.json
Import updates by (target_model, name) and replaces options. It does not copy stored values or media.
Read and write in application code
$user->getCustomFieldValue('department'); // 'engineering'
$user->setCustomFieldValue('bio', 'Hello');
$user->syncCustomFields(['first_name' => 'Ada', 'skills' => ['php', 'laravel']]);
$files = $user->getCustomFieldValue('profile_documents');
// ['collection' => 'custom_field_profile_documents', 'media_ids' => [...], 'files' => [...]]