# Laravel Options Laravel Options is a PHP package by Spatie that transforms various data sources (enums, models, arrays, states) into standardized option arrays for use in HTML select fields, dropdowns, and API responses. It provides a fluent interface for creating, manipulating, filtering, and validating option lists from disparate data types. The package eliminates the repetitive task of manually converting different data structures into label-value pairs for frontend components. It supports native PHP enums, Eloquent models, Spatie enums, MyCLabs enums, Spatie model states, and plain arrays, all with a unified API that includes sorting, filtering, appending extra data, and automatic validation rule generation. ## API Reference ### Options::forEnum() Creates options from PHP native enums, Spatie enums, or MyCLabs enums with automatic label resolution. ```php use Spatie\LaravelOptions\Options; enum Hobbit: string { case Frodo = 'frodo'; case Sam = 'sam'; case Merry = 'merry'; case Pippin = 'pippin'; public static function labels(): array { return [ 'frodo' => 'Frodo Baggins', 'sam' => 'Sam Gamgee', 'merry' => 'Merry Brandybuck', 'pippin' => 'Pippin Took', ]; } } // Basic usage with default label method $options = Options::forEnum(Hobbit::class)->toArray(); // [ // ['label' => 'Frodo Baggins', 'value' => 'frodo'], // ['label' => 'Sam Gamgee', 'value' => 'sam'], // ['label' => 'Merry Brandybuck', 'value' => 'merry'], // ['label' => 'Pippin Took', 'value' => 'pippin'], // ] // Custom label resolution with closure $options = Options::forEnum(Hobbit::class, fn(Hobbit $hobbit) => $hobbit->name . ' from the Shire')->toArray(); // [ // ['label' => 'Frodo from the Shire', 'value' => 'frodo'], // ['label' => 'Sam from the Shire', 'value' => 'sam'], // ['label' => 'Merry from the Shire', 'value' => 'merry'], // ['label' => 'Pippin from the Shire', 'value' => 'pippin'], // ] // Filter specific options with only() $options = Options::forEnum(Hobbit::class)->only(Hobbit::Frodo, Hobbit::Sam)->toArray(); // [['label' => 'Frodo Baggins', 'value' => 'frodo'], ['label' => 'Sam Gamgee', 'value' => 'sam']] // Exclude specific options with except() $options = Options::forEnum(Hobbit::class)->except(Hobbit::Frodo, Hobbit::Sam)->toArray(); // [['label' => 'Merry Brandybuck', 'value' => 'merry'], ['label' => 'Pippin Took', 'value' => 'pippin']] ``` ### Options::forModels() Creates options from Eloquent models, model collections, query builders, or single model instances. ```php use Spatie\LaravelOptions\Options; use App\Models\Wizard; // From model class - fetches all records $options = Options::forModels(Wizard::class)->toArray(); // [ // ['label' => 'Gandalf', 'value' => 1], // ['label' => 'Saruman', 'value' => 2], // ] // From query builder with conditions $options = Options::forModels( Wizard::query()->where('color', 'gray'), label: 'full_name', value: 'uuid' )->toArray(); // From collection $wizards = Wizard::all(); $options = Options::forModels($wizards)->toArray(); // From single model $gandalf = Wizard::first(); $options = Options::forModels($gandalf)->toArray(); // Custom label and value with closures $options = Options::forModels( Wizard::class, label: fn(Wizard $wizard) => $wizard->getName() . ' the ' . $wizard->color, value: fn(Wizard $wizard) => $wizard->uuid )->toArray(); // [ // ['label' => 'Gandalf the Gray', 'value' => '...uuid...'], // ['label' => 'Saruman the White', 'value' => '...uuid...'], // ] // Filter models with only() and except() $options = Options::forModels(Wizard::class)->only(Wizard::where('name', 'gandalf')->first())->toArray(); $options = Options::forModels(Wizard::class)->except(Wizard::where('name', 'saruman')->first())->toArray(); ``` ### Options::forArray() Creates options from associative or indexed arrays. ```php use Spatie\LaravelOptions\Options; // Associative array $kingdoms = [ 'gondor' => 'Gondor', 'rohan' => 'Rohan', 'mordor' => 'Mordor', ]; $options = Options::forArray($kingdoms)->toArray(); // [ // ['label' => 'Gondor', 'value' => 'gondor'], // ['label' => 'Rohan', 'value' => 'rohan'], // ['label' => 'Mordor', 'value' => 'mordor'], // ] // Plain array with labels as values $options = Options::forArray( ['Gondor', 'Rohan', 'Mordor'], useLabelsAsValue: true )->toArray(); // [ // ['label' => 'Gondor', 'value' => 'Gondor'], // ['label' => 'Rohan', 'value' => 'Rohan'], // ['label' => 'Mordor', 'value' => 'Mordor'], // ] // Filter with only() and except() using keys $options = Options::forArray($kingdoms)->only('gondor', 'rohan')->toArray(); // [['label' => 'Gondor', 'value' => 'gondor'], ['label' => 'Rohan', 'value' => 'rohan']] $options = Options::forArray($kingdoms)->except('mordor')->toArray(); // [['label' => 'Gondor', 'value' => 'gondor'], ['label' => 'Rohan', 'value' => 'rohan']] ``` ### Options::forStates() Creates options from Spatie model states with automatic label resolution. ```php use Spatie\LaravelOptions\Options; use App\States\RingState; use App\States\LostRingState; use App\States\DestroyedRingState; class LostRingState extends RingState { public function label(): string { return 'Lost in the Wild'; } } class DestroyedRingState extends RingState { public string $label = 'Destroyed in Mount Doom'; } // Basic usage $options = Options::forStates(RingState::class)->toArray(); // With specific model instance $ring = Ring::find(1); $options = Options::forStates(RingState::class, $ring)->toArray(); // Custom label resolution $options = Options::forStates( RingState::class, label: fn(RingState $state) => strtoupper($state->label()) )->toArray(); // Filter states with only() and except() $options = Options::forStates(RingState::class) ->only(LostRingState::class, DestroyedRingState::class) ->toArray(); $options = Options::forStates(RingState::class) ->except(DestroyedRingState::class) ->toArray(); ``` ### Selectable Interface Implement the Selectable interface on models to define custom option transformation logic. ```php use Spatie\LaravelOptions\Selectable; use Spatie\LaravelOptions\SelectOption; use Spatie\LaravelOptions\Options; use Illuminate\Database\Eloquent\Model; class Wizard extends Model implements Selectable { public function toSelectOption(): SelectOption { return new SelectOption( label: $this->getName(), value: $this->getUuid(), extra: ['color' => $this->color, 'power_level' => $this->power] ); } } // Now forModels() uses the Selectable implementation automatically $options = Options::forModels(Wizard::class)->toArray(); // [ // ['label' => 'Gandalf', 'value' => '...uuid...', 'color' => 'gray', 'power_level' => 9001], // ['label' => 'Saruman', 'value' => '...uuid...', 'color' => 'white', 'power_level' => 8500], // ] // Works with non-model classes too class SelectableOption implements Selectable { public function toSelectOption(): SelectOption { return new SelectOption($this->label, $this->id); } } $options = Options::forSelectableOptions([ SelectableOption::find(1), SelectableOption::find(2), ])->toArray(); ``` ### Manipulation Methods Comprehensive methods for filtering, sorting, appending data, and adding null options. ```php use Spatie\LaravelOptions\Options; enum Hobbit: string { case Frodo = 'frodo'; case Sam = 'sam'; case Merry = 'merry'; case Pippin = 'pippin'; } // Filter with closure $options = Options::forEnum(Hobbit::class) ->filter(fn(Hobbit $hobbit) => $hobbit === Hobbit::Frodo) ->toArray(); // [['label' => 'Frodo', 'value' => 'frodo']] // Reject with closure $options = Options::forEnum(Hobbit::class) ->reject(fn(Hobbit $hobbit) => $hobbit === Hobbit::Frodo) ->toArray(); // [['label' => 'Sam', 'value' => 'sam'], ['label' => 'Merry', 'value' => 'merry'], ['label' => 'Pippin', 'value' => 'pippin']] // Sort alphabetically $options = Options::forEnum(Hobbit::class)->sort()->toArray(); // [['label' => 'Frodo', ...], ['label' => 'Merry', ...], ['label' => 'Pippin', ...], ['label' => 'Sam', ...]] // Sort with closure $options = Options::forEnum(Hobbit::class) ->sort(fn(Hobbit $hobbit) => $hobbit->value) ->toArray(); // Append static data $options = Options::forEnum(Hobbit::class) ->append(['movie' => 'Lord Of The Rings']) ->toArray(); // [ // ['label' => 'Frodo', 'value' => 'frodo', 'movie' => 'Lord Of The Rings'], // ['label' => 'Sam', 'value' => 'sam', 'movie' => 'Lord Of The Rings'], // ... // ] // Append dynamic data with closure $options = Options::forEnum(Hobbit::class) ->append(fn(Hobbit $hobbit) => [ 'ring_bearer' => $hobbit === Hobbit::Frodo || $hobbit === Hobbit::Sam, 'upper' => strtoupper($hobbit->name) ]) ->toArray(); // [ // ['label' => 'Frodo', 'value' => 'frodo', 'ring_bearer' => true, 'upper' => 'FRODO'], // ['label' => 'Sam', 'value' => 'sam', 'ring_bearer' => true, 'upper' => 'SAM'], // ... // ] // Add nullable option $options = Options::forEnum(Hobbit::class)->nullable()->toArray(); // [ // ['label' => '-', 'value' => null], // ['label' => 'Frodo', 'value' => 'frodo'], // ... // ] // Custom nullable label and value $options = Options::forEnum(Hobbit::class) ->nullable(label: 'Select a Hobbit', value: '') ->toArray(); // [['label' => 'Select a Hobbit', 'value' => ''], ['label' => 'Frodo', ...], ...] // Make unique (removes duplicates by value) use App\Models\Character; $model = Character::first(); $options = Options::forModels([$model, $model])->unique()->toArray(); // [['label' => 'Aragon', 'value' => 1]] // Push additional options manually use Spatie\LaravelOptions\SelectOption; $options = Options::forEnum(Hobbit::class) ->push(new SelectOption('Gandalf', 'gandalf')) ->toArray(); // [...hobbits..., ['label' => 'Gandalf', 'value' => 'gandalf']] ``` ### Validation Rules Convert options to Laravel validation rules automatically. ```php use Spatie\LaravelOptions\Options; use Illuminate\Http\Request; enum Hobbit: string { case Frodo = 'frodo'; case Sam = 'sam'; case Merry = 'merry'; case Pippin = 'pippin'; } // Basic validation rule $request->validate([ 'hobbit' => Options::forEnum(Hobbit::class)->toValidationRule() // Generates: ['in:frodo,sam,merry,pippin'] ]); // Nullable validation rule $request->validate([ 'hobbit' => Options::forEnum(Hobbit::class)->nullable()->toValidationRule() // Generates: ['nullable', 'in:frodo,sam,merry,pippin'] ]); // Complete validation example class RingBearerController { public function store(Request $request) { $validated = $request->validate([ 'name' => ['required', 'string', 'max:255'], 'hobbit' => Options::forEnum(Hobbit::class)->toValidationRule(), 'kingdom' => Options::forArray([ 'shire' => 'The Shire', 'gondor' => 'Gondor', 'rohan' => 'Rohan' ])->nullable()->toValidationRule(), ]); // Process validated data return response()->json(['success' => true, 'data' => $validated]); } } ``` ### JSON and Iteration Options can be automatically converted to JSON for API responses and iterated over directly. ```php use Spatie\LaravelOptions\Options; enum Hobbit: string { case Frodo = 'frodo'; case Sam = 'sam'; } // Automatic JSON conversion in controllers class ShowHobbitsController { public function __invoke() { return [ 'hobbits' => Options::forEnum(Hobbit::class), 'message' => 'Fellowship assembled' ]; // JSON: {"hobbits": [{"label": "Frodo", "value": "frodo"}, ...], "message": "..."} } } // Explicit JSON conversion $json = Options::forEnum(Hobbit::class)->toJson(); // '[{"label":"Frodo","value":"frodo"},{"label":"Sam","value":"sam"}]' // Iteration support $options = Options::forEnum(Hobbit::class); foreach ($options as $option) { echo ""; } // // // Array access $array = $options->toArray(); $firstOption = $array[0]; // ['label' => 'Frodo', 'value' => 'frodo'] ``` ### Configuration Customize the keys used in option arrays globally. ```php // config/options.php return [ 'label_key' => 'name', 'value_key' => 'id', ]; // All options now use custom keys $options = Options::forEnum(Hobbit::class)->toArray(); // [ // ['name' => 'Frodo', 'id' => 'frodo'], // ['name' => 'Sam', 'id' => 'sam'], // ['name' => 'Merry', 'id' => 'merry'], // ['name' => 'Pippin', 'id' => 'pippin'], // ] // Publish config file // php artisan vendor:publish --tag="options-config" ``` ## Summary Laravel Options provides a powerful abstraction for converting heterogeneous data sources into consistent option structures for dropdowns, select fields, and API responses. The primary use cases include form generation where enum-based dropdowns need human-readable labels, dynamic select fields populated from database models with custom label/value mappings, and API endpoints that need to return standardized option arrays for frontend consumption. The package shines in applications with complex forms, admin panels with numerous filter dropdowns, and REST APIs that serve option data to multiple frontend frameworks. The integration pattern is straightforward: install via Composer, optionally publish the configuration to customize label/value keys, and use the fluent API in controllers or API resources to transform data. For models that require consistent option formatting across the application, implement the Selectable interface to encapsulate the transformation logic once and reuse it everywhere. The package integrates seamlessly with Laravel's validation system through `toValidationRule()`, automatically generates nullable validation rules, and supports JSON serialization for API responses without additional code.