Custom validation using database lookup
- kevin.waterson@gmail.com
- Member | 81
I have a user registration form, which performs some basic validation.
I wish to add a check if an email address validator to check if the email
already exists in the users database table.
How/Where do custom validators get registered, and how to apply them?
Trying to do soeting like..
$form->addEmail('email', 'Email Address:')
->setRequired('Please enter a valid email Address.')
->addRule($this->userManager->userEmailExists($form['email']), 'Email address already in use', $form['email'])
->addRule(Form::MIN_LENGTH, 'Email must be at least %d characters', 12)
->addRule(Form::MAX_LENGTH, 'Email must be no longer than %d characters', 50);
Last edited by kevin.waterson@gmail.com (2020-07-09 04:46)
- kevin.waterson@gmail.com
- Member | 81
CZechBoY wrote:
You are missing callback function, with this code db lookup is created with each form creation.
OK, thanks, what should I be reading in the docs about callback functions in validation?
- CZechBoY
- Member | 3608
sorry i didnt paste doc which i wanted :D
https://doc.nette.org/…s/validation
Last edited by CZechBoY (2020-07-09 14:13)
- kevin.waterson@gmail.com
- Member | 81
CZechBoY wrote:
sorry i didnt paste doc which i wanted :D
https://doc.nette.org/…s/validation
Hmm, but this would be called every time the form is loaded, not just
submitted.. maybe not what I need.
How best to implement this sort of check?
- CZechBoY
- Member | 3608
if you read docs i sent you could find this
<?php
// user validation: checks if $item is divisible by $arg
// note: this is a real function, not a method in the presenter
function divisibilityValidator(BaseControl $item, int $arg): bool
{
return $item->getValue() % $arg === 0;
}
$form->addInteger('number', 'Number:')
->addRule('divisibilityValidator', 'Number must be divisible by %d.', 8);
?>
Last edited by CZechBoY (2020-07-09 19:11)
- kevin.waterson@gmail.com
- Member | 81
CZechBoY wrote:
if you read docs i sent you could find this
If you read the question I asked, you would see that I had read the docs
and seeking further information.
If all you can respond with is smart ass answers, I would really prefer you not
answer at all, regardless of your knowledge.
- jiri.pudil
- Nette Blogger | 1029
Hmm, but this would be called every time the form is loaded, not just submitted
Quite the opposite. In your original example, the function would be called every time the form is loaded, and wouldn't really validate anything. You need to wrap the invocation in a function/callable which, when used as a validation rule, is called every time a form is validated, and determines whether the submitted value is valid or not.
$form->addEmail('email', 'Email Address:')
->setRequired('Please enter a valid email Address.')
->addRule(fn (TextInput $input) => ! $this->userManager->userEmailExists($input->getValue()), 'Email address already in use');
You can use a named function or a static method instead of an anonymous one,
so that you can use the name to implement client-side validation, but
I don't think client-side validation makes much sense in this particular
use case, so an anonymous function is good enough here it would take some
extra effort in this particular use case because it would require an AJAX
request to the server.
By the way imo a better way to handle this kind of error is by catching the
unique constraint violation exception during the database INSERT because only
then is the whole operation atomic. You can then use
$form['email']->addError('Email address already in use')
to add
the error manually.
Last edited by jiri.pudil (2020-07-10 10:56)
- kevin.waterson@gmail.com
- Member | 81
jiri.pudil wrote:
By the way imo a better way to handle this kind of error is by catching the unique constraint violation exception during the database INSERT because only then is the whole operation atomic. You can then use
$form['email']->addError('Email address already in use')
to add the error manually.
Thanks Jiri, I went with this option, and all is working as expected.