Setting groups
A group bundles related options for a settings or admin screen. It lists its member classes; everything else has sensible defaults:
namespace App\Settings;
use RoundlyConsulting\Options\Groups\OptionGroup;
final class AppearanceSettings extends OptionGroup
{
public function label(): string { return 'Appearance'; }
public function description(): ?string { return 'Look and feel.'; }
/** @return list<class-string<\RoundlyConsulting\Options\OptionInterface>> */
public function options(): array
{
return [LocaleOption::class, ThemeOption::class];
}
}Reading and writing a group
use RoundlyConsulting\Options\Facades\Options;
// Resolve current values, keyed by option key:
Options::group(AppearanceSettings::class)->for($user)->all();
// ['locale' => 'en', 'theme' => 'dark']
// Bulk write by option key or class-string — all or nothing, like setMany(): every value is
// authorized and validated before the first write, and the writes share a transaction
// (then cast, events + observers fire):
Options::group(AppearanceSettings::class)->for($user)->set([
'theme' => 'dark',
LocaleOption::class => 'sk',
]);
// The owner can also be the second argument; options() returns ordered instances:
Options::group(AppearanceSettings::class, $user)->options();all() returns current values keyed by option key. set() accepts option keys or class-strings and is all or nothing, like setMany(): every value is authorized and validated before the first write, and the writes share one transaction — then casts, events and observers apply. An identifier that isn’t a member throws InvalidOptionGroup.
Definitions for a UI
definition() returns a GroupDefinition with everything a form needs:
$page = Options::group(AppearanceSettings::class)->for($user)->definition();
$page->key; // 'appearance-settings'
$page->label; // 'Appearance'
$page->description; // 'Look and feel.'
foreach ($page->options as $field) {
$field->key; // 'theme'
$field->optionClass; // ThemeOption::class
$field->label; // 'Theme'
$field->help; // ?string
$field->section; // ?string
$field->order; // int
$field->type; // the castAs() string, or 'custom' for a cast instance
$field->encrypted; // bool
$field->current; // the resolved value for this scope
$field->default; // the declared default
}Fields are sorted by order() ascending, then by declaration order. definition() reads each member’s current value — one read per option, and one OptionResolved event each if that’s enabled — which is fine for an admin screen.
Presentation metadata
Options can override the metadata definition() uses; all of it defaults sensibly:
public function label(): string { return 'UI Theme'; }
public function help(): ?string { return 'Light or dark.'; }
public function section(): ?string { return 'general'; }
public function order(): int { return 10; }Group keys and scaffolding
A group’s own key() defaults to its kebab-cased class name. To reference a group by a short key, map it under options.groups:
// config/options.php
'groups' => [
'appearance' => App\Settings\AppearanceSettings::class,
],
// anywhere
Options::group('appearance')->for($user)->all();make:option-group scaffolds a group in app/Settings; --options pre-fills the member list:
php artisan make:option-group AppearanceSettings --options="App\Options\ThemeOption,App\Options\LocaleOption"Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.