PHP-在PHP中创建自己的数据验证器:逐步
#教程 #php #laravel #symfony

如何在PHP中创建自己的数据验证器

在本教程中,我将教您如何通过逐步构建我们自己的验证库在PHP中创建自定义数据验证器。对于任何需要确保用户提取的数据有效且安全的开发人员来说,数据验证器都是必不可少的工具。在本教程结束时,您将对如何在PHP中创建自定义数据验证器有深入的了解,这将使您能够更好地处理用户输入并确保应用程序的安全性。

步骤1:创建验证类

第一步是创建一个可以处理验证的类。此类应该能够存储我们要验证的每个字段的验证规则,并在调用时验证这些规则。

这是一个简单验证类的示例:

<?php

namespace DevCoder\Validator;

use DevCoder\Validator\Assert\ValidatorInterface;
use InvalidArgumentException;
use function get_class;
use function gettype;
use function is_array;
use function is_object;
use function sprintf;

class Validation
{
    /**
     * @var array<string,array>
     */
    private $validators;

    /**
     * @var array<string,string>
     */
    private $errors = [];

    /**
     * @var array
     */
    private $data = [];

    public function __construct(array $fieldValidators)
    {
        foreach ($fieldValidators as $field => $validators) {
            if (!is_array($validators)) {
                $validators = [$validators];
            }
            $this->addValidator($field, $validators);
        }
    }

    public function validate(array $data): bool
    {
        $this->data = $data;

        /**
         * @var $validators array<ValidatorInterface>
         */
        foreach ($this->validators as $field => $validators) {
            if (!isset($this->data[$field])) {
                $this->data[$field] = null;
            }

            foreach ($validators as $validator) {
                if ($validator->validate($this->data[$field]) === false) {
                    $this->addError($field, (string)$validator->getError());
                }
            }

        }
        return $this->getErrors() === [];
    }

    /**
     * @return array<string,string>
     */
    public function getErrors(): array
    {
        return $this->errors;
    }

    /**
     * @return array
     */
    public function getData(): array
    {
        return $this->data;
    }

    private function addError(string $field, string $message): void
    {
        $this->errors[$field][] = $message;
    }

    /**
     * @param string $field
     * @param array<ValidatorInterface> $validators
     * @return void
     */
    private function addValidator(string $field, array $validators): void
    {
        foreach ($validators as $validator) {
            if (!$validator instanceof ValidatorInterface) {
                throw new InvalidArgumentException(sprintf(
                    $field . ' validator must be an instance of ValidatorInterface, "%s" given.',
                    is_object($validator) ? get_class($validator) : gettype($validator)
                ));
            }

            $this->validators[$field][] = $validator;
        }
    }
}

步骤2:为数据验证创建规则类

现在我们已经创建了验证器类,下一步是创建我们自己的验证规则。这些规则将用于检查提交的数据是否有效。我们将在单独的文件中创建它们,一个用于每个验证规则。每个验证规则文件应包含以IT实施规则命名的类。例如,如果我们有一个验证规则来检查值是否是整数,我们将命名类整数。

验证器面

<?php

namespace DevCoder\Validator\Assert;

interface ValidatorInterface
{
    public function validate($value): bool;
    public function getError(): ?string;
}

抽象效能器

<?php

namespace DevCoder\Validator\Assert;

abstract class AbstractValidator implements ValidatorInterface
{
    /**
     * @var string|null
     */
    protected $error;

    public function getError(): ?string
    {
        return $this->error;
    }

    protected function error(string $message, array $context): void
    {
        $replace = [];
        foreach ($context as $key => $value) {
            if (is_object($value)) {
                $value = method_exists($value, '__toString') ? (string)$value : get_class($value);
            } elseif (is_array($value)) {
                $value = json_encode($value);
            } else {
                $value = (string)$value;
            }
            $replace['{{ ' . $key . ' }}'] = $value;
        }

        $this->error = strtr($message, $replace);
    }
}

整数

<?php

declare(strict_types=1);

namespace DevCoder\Validator\Assert;

use function ctype_digit;
use function is_int;
use function strval;

class Integer extends AbstractValidator
{
    /**
     * @var string
     */
    private $invalidMessage = 'This value should be of type {{ type }}.';
    private $minMessage = '{{ value }} should be {{ limit }} or more.';
    private $maxMessage = '{{ value }} should be {{ limit }} or less.';

    /**
     * @var int|null
     */
    private $min;
    /**
     * @var int|null
     */
    private $max;

    public function validate($value): bool
    {
        if ($value === null) {
            return true;
        }

        if (ctype_digit(strval($value)) === false) {
            $this->error($this->invalidMessage, ['value' => $value, 'type' => 'integer']);
            return false;
        }

        if (is_int($this->min) && $value < $this->min) {
            $this->error($this->minMessage, ['value' => $value, 'limit' => $this->min]);
            return false;
        }

        if (is_int($this->max) && $value > $this->max) {
            $this->error($this->maxMessage, ['value' => $value, 'limit' => $this->max]);
            return false;
        }

        return true;
    }

    public function invalidMessage(string $invalidMessage): self
    {
        $this->invalidMessage = $invalidMessage;
        return $this;
    }

    public function minMessage(string $minMessage): self
    {
        $this->minMessage = $minMessage;
        return $this;
    }

    public function maxMessage(string $maxMessage): self
    {
        $this->maxMessage = $maxMessage;
        return $this;
    }

    public function min(int $min): self
    {
        $this->min = $min;
        return $this;
    }

    public function max(int $max): self
    {
        $this->max = $max;
        return $this;
    }
}

Notnull

<?php

declare(strict_types=1);

namespace DevCoder\Validator\Assert;

class NotNull extends AbstractValidator
{
    private $message = 'This value should not be null.';

    public function validate($value): bool
    {
        if ($value === null) {
            $this->error($this->message, ['value' => $value]);
            return false;
        }

        return true;
    }

    public function message(string $message): self
    {
        $this->message = $message;
        return $this;
    }
}

步骤3:创建验证类的实例

此对象将一系列验证选项作为输入。数组的键是字段的名称,值是验证器的数组。

<?php
$validation = new Validator([
    'age' => [(new Integer())->min(18)->max(99), new NotNull()],
    'number_of_children' => [new NotNull(), new Integer()],
    'salary' => [new NotNull(), new Integer()],
]);

步骤4:数据验证

创建了验证类的实例后,您可以通过调用验证类的validate()方法来验证数据。如果满足所有验证规则,则此方法将返回true。

<?php

if ($validation->validate($_POST) === true) {
    $data = $validation->getData();
    // save in database
    // redirect in another page
}

return render('template.html.php', [
    'errors' => $validation->getErrors()
]);

可以添加的其他规则的示例

$validation = new Validation([
    'email' => [new NotNull(), new Email()],
    'password' => new NotNull(),
    'firstname' => [new NotNull(), (new StringLength())->min(3), new Alphabetic()],
    'lastname' => [(new StringLength())->min(3)],
    'gender' => new Choice(['Mme', 'Mr', null]),
    'website' => [new NotNull(), new Url()],
    'age' => [new NotNull(), (new Integer())->min(18)],
    'invoice_total' => [new NotNull(), new Numeric()],
    'active' => [new NotNull(), new Custom(function ($value) {
        return is_bool($value);
    })]
]);

要查看可以添加的其他验证规则,请在以下URL上查看我的GitHub存储库:https://github.com/devcoder-xyz/php-validator/tree/main/src/Assert

小型项目的理想选择
简单简单!
https://github.com/devcoder-xyz/php-validator