✏️ Describe the bug
When passing a string that is cast to a boolean with a mapinputname, it returns an Exception when validating
↪️ To Reproduce
<?php
use Spatie\LaravelData\Attributes\MapInputName;
use Spatie\LaravelData\Attributes\WithCast;
use Spatie\LaravelData\Casts\Cast;
use Spatie\LaravelData\Data;
use Spatie\LaravelData\DataPipeline;
use Spatie\LaravelData\DataPipes\AuthorizedDataPipe;
use Spatie\LaravelData\DataPipes\CastPropertiesDataPipe;
use Spatie\LaravelData\DataPipes\DefaultValuesDataPipe;
use Spatie\LaravelData\DataPipes\FillRouteParameterPropertiesDataPipe;
use Spatie\LaravelData\DataPipes\MapPropertiesDataPipe;
use Spatie\LaravelData\DataPipes\ValidatePropertiesDataPipe;
use Spatie\LaravelData\Support\Creation\CreationContext;
use Spatie\LaravelData\Support\DataProperty;
beforeAll(function () {
class BooleanCast implements Cast
{
public function cast(DataProperty $property, mixed $value, array $properties, CreationContext $context): bool
{
return match ($value) {
'yes' => true,
'no' => false,
};
}
}
});
it('should validate boolean with cast', function () {
class BaseData extends Data
{
#[WithCast(BooleanCast::class)]
public bool $boolean;
}
expect(BaseData::validateAndCreate(['boolean' => 'no']))
->toBeInstanceOf(BaseData::class);
});
it('should validate boolean with cast and mapinputname', function () {
class BaseData2 extends Data
{
#[WithCast(BooleanCast::class), MapInputName('bool')]
public bool $boolean;
}
expect(BaseData2::validateAndCreate(['bool' => 'no']))
->toBeInstanceOf(BaseData2::class);
});
it('should validate boolean with cast, mapinputname and alternate pipeline order', function () {
class BaseData3 extends Data
{
#[WithCast(BooleanCast::class), MapInputName('bool')]
public bool $boolean;
public static function pipeline(): DataPipeline
{
return DataPipeline::create()
->into(static::class)
->through(AuthorizedDataPipe::class)
->through(MapPropertiesDataPipe::class)
->through(FillRouteParameterPropertiesDataPipe::class)
->through(CastPropertiesDataPipe::class)
->through(ValidatePropertiesDataPipe::class)
->through(DefaultValuesDataPipe::class);
}
}
expect(BaseData3::validateAndCreate(['bool' => 'no']))
->toBeInstanceOf(BaseData3::class);
});
it('should validate boolean with cast and alternate pipeline order', function () {
class BaseData4 extends Data
{
#[WithCast(BooleanCast::class)]
public bool $boolean;
public static function pipeline(): DataPipeline
{
return DataPipeline::create()
->into(static::class)
->through(AuthorizedDataPipe::class)
->through(MapPropertiesDataPipe::class)
->through(FillRouteParameterPropertiesDataPipe::class)
->through(CastPropertiesDataPipe::class)
->through(ValidatePropertiesDataPipe::class)
->through(DefaultValuesDataPipe::class);
}
}
expect(BaseData4::validateAndCreate(['boolean' => 'no']))
->toBeInstanceOf(BaseData4::class);
});
✅ Expected behavior
The field is validated after it's cast to a boolean. It also should not try to validate the original property name.
Validation always runs before casting, that's at the moment how it works in v5 we're going to try rethinking this but at the moment it is not an easy fix.
✏️ Describe the bug When passing a string that is cast to a boolean with a mapinputname, it returns an Exception when validating
↪️ To Reproduce
✅ Expected behavior The field is validated after it's cast to a boolean. It also should not try to validate the original property name.
🖥️ Versions
Laravel: 10.10 Laravel Data: 4.5.1 PHP: 8.2