Kończymy walidator, tak aby wszystko robił za nas automatycznie. Do dzieła.
Nasze formData i formRules:
<?php
$form_rules = [
'email' => ['required', 'email'],
'password' => ['required'],
'confirmPassword' => ['required', 'match:password'],
'name' => ['unique:people.name', 'maxLength:20'],
'country' => ['in:USA,Poland'],
'age' => ['min:18']
];
$form_data = [
'email' => 'john.doe@gmail.com',
'password' => md5('helloworld'),
'confirmPassword' => md5('helloworld'),
'name' => 'Janet',
'country' => 'USA',
'age' => 19
];
Poniżej interfejs i klasy z lekcji poprzednich:
interface RuleInterface
{
public function validate(array $data, string $field, array $params): bool;
public function getMessage(array $data, string $field, array $params): string;
}
class RequiredRule implements RuleInterface
{
//(...)
}
class EmailRule implements RuleInterface
{
//(...)
}
class UrlRule implements RuleInterface
{
//(...)
}
class MatchRule implements RuleInterface
{
//(...)
}
class ConfigINI {
//(...)
}
class PDOConnection {
//(...)
}
class UniqueRule implements RuleInterface
{
//(...)
}
class InRule implements RuleInterface
{
//(...)
}
class MinRule implements RuleInterface
{
//(...)
}
class LengthMaxRule implements RuleInterface
{
//(...)
}
Zrobimy sobie autoloading już niedługo. Na razie jednak piszmy naszą klasę:
class Validator
{
private array $rules = [];
public function add(string $alias, RuleInterface $rule)
{
$this->rules[$alias] = $rule;
return $this;
}
public function validate(array $formData, array $fields)
{
$errors = [];
if(count($errors))
print_r($errors);
}
}
Metodę validate jeszcze sobie naprawimy, na razie jednak utwórzmy walidator:
$validator = new Validator;
$validator->add('required', new RequiredRule)
->add('email', new EmailRule)
->add('min', new MinRule)
->add('in', new InRule)
->add('match', new MatchRule)
->add('maxLength', new LengthMaxRule)
->add('unique', new UniqueRule);
$validator->validate($form_data, $form_rules);
Fluent-interface (return this) to świetna sprawa, możemy metody wywoływać łańcuchowo. Teraz tylko naprawmy validate:
class Validator
{
private array $rules = [];
//(...)
public function validate(array $formData, array $fields)
{
$errors = [];
foreach ($fields as $fieldName => $rules) {
foreach ($rules as $rule) {
$ruleParams = [];
if (str_contains($rule, ':')) {
[$rule, $ruleParams] = explode(':', $rule);
$ruleParams = explode(',', $ruleParams);
}
$ruleValidator = $this->rules[$rule];
if ($ruleValidator->validate($formData, $fieldName, $ruleParams)) {
continue;
}
$errors[$fieldName][] = $ruleValidator->getMessage(
$formData,
$fieldName,
$ruleParams
);
}
}
if (count($errors)) {
print_r($errors);
}
}
}
Nie różni się to nic od parsowania z lekcji poprzedniej, tylko tym razem używamy danych z form_rules zamias je wyświetlać.
Jeżeli nie widzimy nic to znaczy, że nasze dane przechodzą walidację.
Popsujmy coś – u mnie jest to zamiana 'Janet’ na 'Jane’:
$form_rules = [
'email' => ['required', 'email'],
'password' => ['required'],
'confirmPassword' => ['required', 'match:password'],
'name' => ['unique:people.name', 'maxLength:20'],
'country' => ['in:USA,Poland'],
'age' => ['min:18']
];
$form_data = [
'email' => 'john.doe@gmail.com',
'password' => md5('helloworld'),
'confirmPassword' => md5('helloworld'),
'name' => 'Jane',
'country' => 'USA',
'age' => 19
];
//(...)
$validator = new Validator;
//(...)
$validator->validate($form_data, $form_rules);
//Array ( [name] => Array ( [0] => Field people.name already in use! ) )
Jedyne co nam zostało to errory nie wyświetlać jako print_r, ale w prawdziwy Error wrzucać i obsługiwać ich wyświetlanie, ale tym zajmiemy się później.