Validation
Validation copied to clipboard
Formatter inconsequently stringifies values
Is it intended behaviour for Formatter to use the stringify()
function instead of the the class parameter $parameterStringifier
when converting the the name
parameter?
Personally I think it's a bug since I tried to replace the ParameterStringifier
using the Factory
but the name passes through the default built-in stringifier instead of the one I provided.
My use case was that I wanted to replace the DateTimeStringifier
from respect/stringifer:0.2.0
that this project uses, since the value is rather poorly formatted. This has been fixed in 2.0.0
but I can't use it because of the requirements of this project.
@jonsa sorry for the delay answering this. I need some more time to investigate this.
If you are able to provide some code samples of the usage you intend, that would be super helpful!
Thanks for reporting! I'll get back at this soon.
This is a somewhat lengthy example. I could probably bake everything into MyParameterStringifier
but I wanted to keep the essence of the structure used in this project and my own solution intact.
<?php
declare(strict_types=1);
use Respect\Stringifier\Stringifier;
use Respect\Stringifier\Stringifiers;
use Respect\Validation\Message\ParameterStringifier;
require_once __DIR__ . '/vendor/autoload.php';
class MyDateStringifier implements Stringifier
{
public function stringify($raw, int $depth): ?string
{
return $raw instanceof \DateTimeInterface
? $raw->format('Y-m-d')
: null;
}
}
class MyStringifier implements Stringifier
{
private array $stringifiers;
public function __construct()
{
$this->stringifiers = [
new MyDateStringifier(),
new Stringifiers\JsonParsableStringifier(),
];
}
public function stringify($raw, int $depth): ?string
{
foreach ($this->stringifiers as $stringifier) {
$string = $stringifier->stringify($raw, $depth);
if (null === $string) {
continue;
}
return $string;
}
return null;
}
}
class MyParameterStringifier implements ParameterStringifier
{
private MyStringifier $stringifier;
public function __construct()
{
$this->stringifier = new MyStringifier();
}
public function stringify(string $name, $value): string
{
if ($name === 'name' && is_string($value)) {
return $value;
}
return $this->stringifier->stringify($value, 0);
}
}
Respect\Validation\Factory::setDefaultInstance(
Respect\Validation\Factory::getDefaultInstance()
->withParameterStringifier(new MyParameterStringifier())
);
$v = Respect\Validation\Validator::between(new DateTime('2023-01-01'), new DateTime('2023-12-31'));
try {
$v->assert(new DateTime('2022-06-01'));
} catch (Respect\Validation\Exceptions\AllOfException $e) {
var_export($e->getMessages());
}
This will result in
array (
'between' => '`[date-time] (DateTime: "2022-06-01T00:00:00+02:00")` must be between 2023-01-01 and 2023-12-31',
)
As you can see the value is passed through DateTimeStringifier which I defined not to be used.
In my attempts to fix the issue I found that editing Formatter.php#40 to be
$parameters['name'] = $parameters['name'] ?? $this->parameterStringifier->stringify('name', $input);
solves my issue.
Hey @jonsa!
I'm sorry about my delay... What you were describing is really a bug.
However, we've upgraded the version of respect/stringifer
. How are you experiencing it now?
I just merged fb322df1dac40c890faf40652089ea653f103c14, I should release a patch version soon.
This fix is available on version 2.3.3
Thank you for reporting, @jonsa! 🐼