nette / schema

📐 Validating data structures against a given Schema.
https://doc.nette.org/schema
Other
905 stars 26 forks source link

String to DateTime returns \Nette\Utils\Arrays error #44

Closed vitek-dev closed 2 years ago

vitek-dev commented 3 years ago

Bug Description

I am not sure, if I am using this right, but I am trying to convert input string to result DateTime object

Steps To Reproduce

https://fiddle.nette.org/nette/#4f2cd78abf

class Foo {
    public \DateTime $bar;
}

$processor = new \Nette\Schema\Processor;
$processor->process(
    \Nette\Schema\Expect::structure([
        'bar' => \Nette\Schema\Expect::string()->castTo('DateTime')
    ])->castTo(Foo::class),
    [
        'bar' => '2021-01-01',
    ]
);

Will result in the error:

Nette\Utils\Arrays::toObject(): Argument #1 ($array) must be of type iterable, string given, called in ...../vendor/nette/schema/src/Schema/Elements/Base.php on line 174

Expected Behavior

Input string will be successfully mapped to target class DateTime property.

SeriousKen commented 2 years ago

I just came across this and I think the way cast works isn't properly explained in the documentation. All it does is instantiate an object and then map an array to public properties. It also won't work with any type that has constructor arguments.

I think you should use normalization - the following works:

$schema = Expect::structure([
    'created_at' => Expect::type(DateTime::class)->before(function ($date) {
        return new DateTime($data);
    }),
]);