anomaly/checkboxes-field_type
A PyroCMS field type that adds a group of checkboxes to your forms, letting users select multiple options at once and storing the selections as structured values for easy use in entries and templates.
Install the addon via Composer and register it with the Streams Platform before it can be referenced by any stream:
composer require anomaly/checkboxes-field_type
php artisan addon:install anomaly.checkboxes_field_type
Places to look first:
src/CheckboxesFieldType.php — the field type class itself; this is where getOptions(), the input view, and any accessor/mutator live.resources/config/config.php — declares the options configuration the admin UI exposes.resources/views/input.twig / output.twig — how the checkbox list is rendered and how stored values are displayed.resources/lang/en/addon.php / config.php — labels, instructions, and validation messages.A first real use case is a "features" or "tags-like" field on an entries stream. Add it to a stream either through the control panel (Fields → Add Field → Checkboxes) or in a seeder/migration:
$stream->createField('features', [
'type' => 'anomaly.field_type.checkboxes',
'config' => [
'options' => [
'wifi' => 'Wi-Fi',
'parking' => 'Parking',
'breakfast' => 'Breakfast',
],
],
]);
The stored value is an array of the selected keys (['wifi', 'breakfast']), so the field type is intended for multi-select, not boolean toggles.
Field definition. Declare the field type as anomaly.field_type.checkboxes and pass a flat associative options array (key => label). Keys are what get persisted; labels are display-only and can be changed later without migrating data.
Reading values. Because the addon uses the Streams Multiple trait, the value is exposed as a PHP array on the entry object:
$entry->features; // ['wifi', 'parking']
In Twig the same array is available directly, which is convenient for badge-style output:
{% for key, label in entry.fields.features.field_type.options %}
{% if key in entry.features %}
<span class="badge">{{ label }}</span>
{% endif %}
{% endfor %}
Forms and validation. Treat the field as an array in Form Requests and validators. Useful rules:
'features' => 'array',
'features.*' => 'in:wifi,parking,breakfast',
If you need "at least one" selection, add 'features' => 'required|array|min:1' — a plain required alone won't catch empty arrays in every Laravel version.
Querying entries. Since values are stored as JSON (or comma-separated text depending on the field's column type), query with the matching driver support. On Laravel/MySQL 5.7+:
EntryModel::whereJsonContains('features', 'wifi')->get();
On older MySQL or Postgres the safest portable approach is a where('features', 'like', '%"wifi"%') fallback, or denormalize a boolean index column if you query heavily.
Dynamic option sources. Rather than hard-coding the options array, implement Anomaly\Streams\Platform\FieldType\OptionsInterface on a class and point the field's source config at it. This is the cleanest way to drive checkboxes from a database table (e.g., available amenities that admins manage elsewhere) without editing field config on every change.
Reusable form partials. In admin forms, let the field type render itself via {{ form.fields.features }} rather than hand-rolling checkboxes — you inherit the configured labels, instructions, and error display automatically.
[], not null. Guard code with (array) $entry->features when writing to APIs or views that expect a list.Multiple accessor/mutator stores JSON in most configurations. Confirm the underlying column type on the stream's migration — an integer or short string column will truncate and cause silent data loss.required. Laravel's required rule passes for [] only in some versions/scenarios; pair it with array|min:1 if emptiness should fail validation.resources/lang/{locale}/validation.php in your app if you want custom wording; editing the vendor files directly will be lost on composer update.resources/views/input.twig into resources/views/vendor/anomaly/checkboxes-field_type/input.twig (or the project's addon override path) rather than patching vendor.php artisan view:clear) after changing Twig views — Streams caches aggressively. Also check storage/framework/views for the compiled output when a change doesn't appear.OptionsInterface for dynamic sources, override getOptions() on a subclass for computed option sets, and use the Multiple trait's $accessor/$mutator hooks if you need a different storage format than the default.composer.json and add an entry-integration test, because upstream Streams changes may land without a coordinated release here.How can I help you explore Laravel packages today?