Update respect/validation to ^2.0
Closed this issue · 14 comments
Is it possible to update respect/validation to version 2.x?
Hi
I also would be happy, if SlimValidation would use respect/validation 2.x. Recently I noticed, that with PHP8.2 I get notices when using the emailValidator of respect/validation 1.x because of creation of dynamic property, which is deprecated with PHP8.2.
Thanks to seateng who made PR #23 , which would use respect/validation 2.x.
Is there a special reason, why this PR isn't merged?`
For me the changes in the PR worked without errors.
Thanks to all the contributors of this Repo!
philipp
PR #23 is not enough to make the validator compatible with respect/validation 2.x, it requires a bit more work than that, plus it introduces breaking changes. Version 3.x should stay compatible with respect/validation 1.x, adding support for both versions would require a lot more work, I would prefer creating a new major version compatible with respect/validation 2.x only. The work has already been done in branch 4.x but it is not ready to be released yet.
This is a project I developed as a student, there are probably better alternatives. I am not happy with the code quality so I tried a complete rewrite, but since I don't know why and how people continue to use this, I don't know in which direction I should go. If you could tell me a bit about your usage of the validator, maybe I'll consider taking the time to continue its development and release a new version.
Hi Alexis
Thanks a lot for your reply.
I absolutely see your point. I also think it would be a good idea to release a new major version for respect/validation 2.x.
I use your validator in a webshop which I built on Slim Framework, Twig and Eloquent. I think it was in the beginning slim3 and because I use Twig I used your library. Meanwhile the shop runs on Slim4.
At the moment I'm working on bumping my app to php8.2 and there I get deprecation notices because of respect/validation 1.x.
You wrote, that the work for a new major version for respect/validation 2.x has been done in branch 4.x. Is there a way that I could support you to release this?
philipp
You wrote, that the work for a new major version for respect/validation 2.x has been done in branch 4.x. Is there a way that I could support you to release this? philipp
I also like this library and would like to support your effort to upgrade it to a newer version of Respect\Validation
.
Thank you for your effort, @awurth, it seems your project is really useful to people. If there's any way to give you money to compensate your efforts, please let us know!
I'm using the library in a Slim 4 project, slowly modernizing a legacy codebase's API. Quickly validating a request and getting clean error messages that I can easily render as JSON is very useful.
I actually learned about Respect\Validation
because of your library, I think SlimValidation
is listed somewhere on the main Slim website.
Hi, sorry for the late response, and thank you for your feedback. I'm about to release a version 5.0 (I'm skipping v4.x) but I need some more feedback first since some features (that you might have been using) have been removed:
- The minimum required PHP version is now 8.1
- There is no more a Twig Extension to display error messages in a Twig template. The extension was possible because the validator was used to store all the errors, but now the validator just returns a collection of errors
- Error groups and the option to store errors in an associative or indexed array no longer exist, all errors are stored in a
ValidationFailureCollection
Are you ok with these changes?
Those all seem good. The project I'm working on doesn't use Twig, and the ValidationFailureCollection
is a neutral API change. Thanks for all your hard work!
Hi Alexis
Thanks a lot for your reply!
The minimum requirement of PHP 8.1 for me is fine.
That there is no more a Twig Extension is a problem for me. I used your library especially because of this feature. So I would have to rewrite a lot of Twig Templates to somehow still display the errors.
So, for me, this wouldn't be a good change, but I don't expect you to develop your library according to my personal needs.
@codingphildotdev I added a new SatefulValidator
that decorates the base Validator
class and holds all the errors. I copied the old Twig Extension, renamed it LegacyValidatorExtension
and adapted the code to the new API, but I had to remove the val
function since you can only get values from the ValidationFailureCollection
which only contains the invalid values. I'll try to find a way to collect all values passed to the validator.
So you don't have to change your templates, but only the instanciation of the validator and the Twig extension:
use Awurth\Validator\StatefulValidator;
use Awurth\Validator\Twig\LegacyValidatorExtension;
$validator = StatefulValidator::create();
$extension = new LegacyValidatorExtension($validator);
I finally found a way to collect all validated data. You must create a DataCollectorAsserter
instance and pass it to your StatefulValidator
, then use that same instance and pass it to the ValidatorExtension
:
use Awurth\Validator\Assertion\DataCollectorAsserter;
use Awurth\Validator\StatefulValidator;
use Awurth\Validator\Twig\LegacyValidatorExtension;
$asserter = DataCollectorAsserter::create();
$validator = StatefulValidator::create($asserter);
$extension = new LegacyValidatorExtension($validator, $asserter);
Now you can use the val
function in templates to pre-fill fields with submitted data.
If these changes seem fine to you I'll tag a new version and then I'll update the docs when I have the time
Thanks a lot for your effort!
It looks quite good!
As I use PHP-DI I had to create the DataCollectorAsserter
and the StatefulValidator
in my app.php like this:
use Awurth\Validator\Assertion\DataCollectorAsserter;
use Awurth\Validator\StatefulValidator;
use Awurth\Validator\Twig\LegacyValidatorExtension;
DataCollectorAsserter::class => function(){
return DataCollectorAsserter::create();
},
StatefulValidator::class => function(ContainerInterface $container){
return StatefulValidator::create($container->get(DataCollectorAsserter::class));
},
'view' => function(ContainerInterface $container){
$view = Twig::create(__DIR__ . '/../ressources/views',['cache' => false]);
$view->addExtension(new LegacyValidatorExtension($container->get(StatefulValidator::class), $container->get(DataCollectorAsserter::class)));
);
Then in my Controller I can use the validator with dependency injection like this:
use Awurth\Validator\StatefulValidator;
class KundenkontoController
{
protected $validator;
public function __construct(StatefulValidator $validator) {
$this->validator = $validator;
}
//Validation
$validator = $this->validator->validate($request, [
'email' => [
'rules' => v::notEmpty()->email(),
'messages' => [
'notEmpty' => 'Bitte geben Sie Ihre Email-Adresse ein.',
'email' => 'Bitte geben Sie eine gültige Email-Adresse ein.'
]
],
'passwort' => [
'rules' => v::notEmpty(),
'messages' => [
'notEmpty' => 'Bitte geben Sie Ihr Passwort ein.',
]
],
]);
if($validator->count() > 0){
return $this->view->render($response, 'kundenkonto/login.twig');
}
In the Twig-Templates I can use the val
function with no issues.
What I realized is, that it's no longer possible to use $validator->isValid()
which I used a lot. Of course I can use $validator->count() > 0
but I think the isValid()
function was quite handy.
On some occasions I also made checks independent of the validator but added custom errors, which I could use in the Twig Template. Like this:
if(!$this->kundeAuth->attempt($request->getParam('email'), $request->getParam('passwort'))){
$validator->addError('email', 'Bitte geben Sie gültige Logindaten an.');
$validator->addError('passwort', 'Bitte geben Sie gültige Logindaten an. <a href="/kundenkonto/passwortvergessen">Passwort vergessen?</a>');
return $this->view->render($response, 'kundenkonto/login.twig');
}
Now $validator->addError()
doesn't work anymore.
Is there a way to add Errors in Code?
Thanks!
You can add errors like that: $validator->getFailures()->add(new ValidationFailure('message', 'value', 'property', 'notBlank'));
I'd rather not add those methods directly in the Validator
, or at least not with the same signature, but I made pretty much everything extendable, so you could create your own StatefulValidator
by implementing the StatefulValidatorInterface
and implement those methods in it.
It would look something like this:
Method 1, decorating the base Validator
:
final class MyCustomValidator implements StatefulValidatorInterface
{
private ValidationFailureCollectionInterface $failures;
public function __construct(private readonly ValidatorInterface $validator)
{
$this->failures = new ValidationFailureCollection();
}
public function validate(mixed $subject, Validatable|array $rules, array $messages = []): ValidationFailureCollectionInterface
{
$this->failures->addAll($this->validator->validate($subject, $rules, $messages));
return $this->failures;
}
public function getFailures(): ValidationFailureCollectionInterface
{
return $this->failures;
}
public function isValid(): bool
{
return $this->failures->count() === 0;
}
public function addError(string $key, string $message): void
{
$this->failures->add(new ValidationFailure($message, null, $key));
}
}
Method 2, decorating the StatefulValidator
:
final class MyCustomValidator implements StatefulValidatorInterface
{
public function __construct(private readonly StatefulValidatorInterface $validator)
{
}
public function validate(mixed $subject, Validatable|array $rules, array $messages = []): ValidationFailureCollectionInterface
{
return $this->validator->validate($subject, $rules, $messages);
}
public function getFailures(): ValidationFailureCollectionInterface
{
return $this->validator->getFailures();
}
public function isValid(): bool
{
return $this->validator->getFailures()->count() === 0;
}
public function addError(string $key, string $message): void
{
$this->validator->getFailures()->add(new ValidationFailure($message, null, $key));
}
}
Great!
Using a Custom Class works superb!
I hope the last thing I encountered was that the LegacyValidatorExtension
offers the hasError()
function, but it's not possible to restrict it on a certain HTML-Form on the page.
Before in the ValidatorExtension
:
/**
* Tells whether there are validation errors for a parameter.
*
* @param string $key
* @param string $group
*
* @return bool
*/
public function hasError($key, $group = null)
{
return !empty($this->validator->getErrors($key, $group));
}
With this I could use {{ has_error('fieldname', 'formname') ? ' is-invalid' : ''}}
which now obviously gives me an error as the second argument for the new getError
function expects an integer.
Is there a way to handle this?
I've just added the possibility to pass a context as 4th argument of the validate
method (it can be anything, not just a string):
$validator->validate('Too short', V::notBlank()->length(min: 10), context: 'formname');
Now your Twig templates should work as before
Hi Alexis
I'm really sorry, that I didn't reply sooner.
I was travelling through Europe in April during the whole month and started a new job in May.
Finally I tested the context argument of the validate method, which works flawlessly.
Again thanks a lot for your great work!