Skip to content

Commit 35d47db

Browse files
Update validation rule code
1 parent ec3016b commit 35d47db

File tree

3 files changed

+64
-76
lines changed

3 files changed

+64
-76
lines changed

README.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -429,18 +429,21 @@ Options::empty();
429429

430430
### Using for validation
431431

432-
For convenience, you can quickly turn the same options you passed to the front end, as a back end validation rule.
433-
This will account for nullable options too.
432+
Options, can be converted to a Laravel validation rule:
434433

435434
```php
436-
$options = Options::forArray([
437-
'gondor' => 'Gondor',
438-
'rohan' => 'Rohan',
439-
'mordor' => 'Mordor',
440-
]);
435+
$request->validate([
436+
// ['in:frodo,sam,merry,pippin']
437+
'hobbit' => Options::forEnum(Hobbit::class)->toValidationRule()
438+
]);
439+
```
441440

441+
When options are nullable, the validation rule automatically will become nullable:
442+
443+
```php
442444
$request->validate([
443-
'my_options_input' => $options->toValidationRule()
445+
// ['nullable', 'in:frodo,sam,merry,pippin']
446+
'hobbit' => Options::forEnum(Hobbit::class)->nullable()->toValidationRule()
444447
]);
445448
```
446449

src/Options.php

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Illuminate\Support\Arr;
1515
use Illuminate\Support\Collection;
1616
use Illuminate\Validation\Rule;
17+
use Illuminate\Validation\Rules\In;
1718
use JsonSerializable;
1819
use MyCLabs\Enum\Enum as MyclabsEnum;
1920
use Spatie\Enum\Enum as SpatieEnum;
@@ -168,6 +169,41 @@ public function push(SelectOption ...$options): self
168169

169170
public function toArray(): array
170171
{
172+
return $this->resolveOptions()->toArray();
173+
}
174+
175+
/**
176+
* @return array<string|In>
177+
*/
178+
public function toValidationRule(): array
179+
{
180+
$rulesArray = [Rule::in($this->resolveOptions(enableNullOption: false)->pluck('value'))];
181+
182+
if ($this->nullable) {
183+
$rulesArray[] = 'nullable';
184+
}
185+
186+
return $rulesArray;
187+
}
188+
189+
public function toJson($options = 0)
190+
{
191+
return json_encode($this, flags: JSON_THROW_ON_ERROR);
192+
}
193+
194+
public function __toString()
195+
{
196+
return json_encode($this, flags: JSON_THROW_ON_ERROR);
197+
}
198+
199+
public function jsonSerialize(): mixed
200+
{
201+
return $this->toArray();
202+
}
203+
204+
private function resolveOptions(
205+
bool $enableNullOption = true,
206+
): Collection {
171207
return $this->provider
172208
->provide()
173209
->when($this->filter instanceof Closure, fn(Collection $collection) => $collection->filter($this->filter))
@@ -198,42 +234,11 @@ public function toArray(): array
198234
))
199235
->values()
200236
->when(
201-
$this->nullable === true,
237+
$this->nullable === true && $enableNullOption,
202238
fn(Collection $collection) => $collection->prepend(new SelectOption(
203239
$this->nullableLabel,
204240
null
205241
))
206-
)
207-
->toArray();
208-
}
209-
210-
/**
211-
* @return array<int, string|In>
212-
*/
213-
public function toValidationRule(): array
214-
{
215-
$rulesArray = [];
216-
if ($this->nullable) {
217-
$rulesArray[] = 'nullable';
218-
}
219-
220-
$rulesArray[] = Rule::in(array_filter(Arr::pluck($this->toArray(), 'value')));
221-
222-
return $rulesArray;
223-
}
224-
225-
public function toJson($options = 0)
226-
{
227-
return json_encode($this, flags: JSON_THROW_ON_ERROR);
228-
}
229-
230-
public function __toString()
231-
{
232-
return json_encode($this, flags: JSON_THROW_ON_ERROR);
233-
}
234-
235-
public function jsonSerialize(): mixed
236-
{
237-
return $this->toArray();
242+
);
238243
}
239244
}

tests/OptionsTest.php

Lines changed: 15 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?php
22

3+
use Illuminate\Validation\Rules\In;
34
use Spatie\LaravelOptions\Options;
45
use Spatie\LaravelOptions\Providers\NativeEnumProvider;
56
use Spatie\LaravelOptions\SelectOption;
@@ -9,7 +10,7 @@
910

1011
it('can filter options', function () {
1112
$options = Options::create(new NativeEnumProvider(StringEnum::class))
12-
->filter(fn (StringEnum $enum) => $enum === StringEnum::Frodo)
13+
->filter(fn(StringEnum $enum) => $enum === StringEnum::Frodo)
1314
->toArray();
1415

1516
expect($options)->toBeArray()->toBe([
@@ -19,7 +20,7 @@
1920

2021
it('can reject options', function () {
2122
$options = Options::create(new NativeEnumProvider(StringEnum::class))
22-
->reject(fn (StringEnum $enum) => $enum === StringEnum::Frodo)
23+
->reject(fn(StringEnum $enum) => $enum === StringEnum::Frodo)
2324
->toArray();
2425

2526
expect($options)->toBeArray()->toBe([
@@ -44,7 +45,7 @@
4445

4546
it('can sort options using closure', function () {
4647
$options = Options::create(new NativeEnumProvider(StringEnum::class))
47-
->sort(fn (StringEnum $enum) => match ($enum) {
48+
->sort(fn(StringEnum $enum) => match ($enum) {
4849
StringEnum::Frodo => 4,
4950
StringEnum::Sam => 3,
5051
StringEnum::Merry => 2,
@@ -81,7 +82,7 @@
8182
$model = Character::factory()->create();
8283

8384
$options = Options::forModels([$model, $model])
84-
->unique(fn (Character $character) => $character->getKey())
85+
->unique(fn(Character $character) => $character->getKey())
8586
->toArray();
8687

8788
expect($options)->toBeArray()->toBe([
@@ -92,7 +93,7 @@
9293
it('can add a null option', function () {
9394
$options = Options::create(new NativeEnumProvider(StringEnum::class))
9495
->nullable()
95-
->sort(fn (StringEnum $enum) => match ($enum) {
96+
->sort(fn(StringEnum $enum) => match ($enum) {
9697
StringEnum::Frodo => 4,
9798
StringEnum::Sam => 3,
9899
StringEnum::Merry => 2,
@@ -139,7 +140,7 @@
139140

140141
it('can append data using closure', function () {
141142
$options = Options::create(new NativeEnumProvider(StringEnum::class))
142-
->append(fn (StringEnum $enum) => ['upper' => strtoupper($enum->name)])
143+
->append(fn(StringEnum $enum) => ['upper' => strtoupper($enum->name)])
143144
->toArray();
144145

145146
expect($options)->toBeArray()->toBe([
@@ -178,7 +179,7 @@
178179
Character::factory()->create(['name' => 'Aragon', 'kind' => 'Men']);
179180

180181
$options = Options::forModels(SelectableCharacter::class)
181-
->append(fn (SelectableCharacter $character) => ['upper_name' => strtoupper($character->name)])
182+
->append(fn(SelectableCharacter $character) => ['upper_name' => strtoupper($character->name)])
182183
->toArray();
183184

184185
expect($options)->toBeArray()->toBe([
@@ -192,42 +193,21 @@
192193
});
193194

194195
it('can be turned into a laravel validation rule', function () {
195-
$rules = Options::create(new NativeEnumProvider(StringEnum::class))
196-
->toValidationRule();
196+
$rules = Options::create(new NativeEnumProvider(StringEnum::class))->toValidationRule();
197197

198198
expect($rules)
199199
->toBeArray()
200-
->toHaveCount(1);
201-
202-
$options = $rules[0];
203-
$optionsString = $options->__toString();
204-
205-
expect($options)->toBeInstanceOf(\Illuminate\Validation\Rules\In::class);
206-
expect($optionsString)
207-
->toBeString()
208-
->toBe('in:"frodo","sam","merry","pippin"');
200+
->toHaveCount(1)
201+
->toEqual([new In(['frodo', 'sam', 'merry', 'pippin'])]);
209202
});
210203

211204
it('can be turned into a laravel validation rule when nullable', function () {
212205
$rules = Options::create(new NativeEnumProvider(StringEnum::class))
213-
->nullable()
214-
->toValidationRule();
206+
->nullable()
207+
->toValidationRule();
215208

216209
expect($rules)
217210
->toBeArray()
218-
->toHaveCount(2);
219-
220-
$nullable = $rules[0];
221-
222-
expect($nullable)
223-
->toBeString()
224-
->toBe('nullable');
225-
226-
$options = $rules[1];
227-
$optionsString = $options->__toString();
228-
229-
expect($options)->toBeInstanceOf(\Illuminate\Validation\Rules\In::class);
230-
expect($optionsString)
231-
->toBeString()
232-
->toBe('in:"frodo","sam","merry","pippin"');
211+
->toHaveCount(2)
212+
->toEqual([new In(['frodo', 'sam', 'merry', 'pippin']), 'nullable']);
233213
});

0 commit comments

Comments
 (0)