Валидация
Phalcon\Validation — это независимый компонент валидации, который проверяет произвольный набор данных. Этот компонент можно использовать для реализации правил валидации на объектах данных, которые не относятся к модели или коллекции.
Следующий пример демонстрирует его базовое использование:
use Phalcon\Validation;
use Phalcon\Validation\Validator\Email;
use Phalcon\Validation\Validator\PresenceOf;
$validation = new Validation();
$validation->add(
"name",
new PresenceOf(
[
"message" => "The name is required",
]
)
);
$validation->add(
"email",
new PresenceOf(
[
"message" => "The e-mail is required",
]
)
);
$validation->add(
"email",
new Email(
[
"message" => "The e-mail is not valid",
]
)
);
$messages = $validation->validate($_POST);
if (count($messages)) {
foreach ($messages as $message) {
echo $message, "<br>";
}
}
Гибкая структура этого компонента позволяет вам создавать собственные валидаторы, а также использовать те, которые предоставляет фреймворк.
Инициализация валидации
Цепочки валидации можно инициализировать напрямую, добавляя валидаторы в объект Phalcon\Validation. Для лучшей повторной используемости и организации вы можете разместить свои валидации в отдельном файле:
use Phalcon\Validation;
use Phalcon\Validation\Validator\Email;
use Phalcon\Validation\Validator\PresenceOf;
class MyValidation extends Validation
{
public function initialize()
{
$this->add(
"name",
new PresenceOf(
[
"message" => "The name is required",
]
)
);
$this->add(
"email",
new PresenceOf(
[
"message" => "The e-mail is required",
]
)
);
$this->add(
"email",
new Email(
[
"message" => "The e-mail is not valid",
]
)
);
}
}
Затем инициализируйте и используйте свой собственный валидатор:
$validation = new MyValidation();
$messages = $validation->validate($_POST);
if (count($messages)) {
foreach ($messages as $message) {
echo $message, "<br>";
}
}
Валидаторы
Phalcon предоставляет набор встроенных валидаторов для этого компонента:
Следующий пример объясняет, как создавать дополнительные валидаторы для этого компонента:
use Phalcon\Validation;
use Phalcon\Validation\Message;
use Phalcon\Validation\Validator;
class IpValidator extends Validator
{
/**
* Executes the validation
*
* @param Phalcon\Validation $validator
* @param string $attribute
* @return boolean
*/
public function validate(Validation $validator, $attribute)
{
$value = $validator->getValue($attribute);
if (!filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) {
$message = $this->getOption("message");
if (!$message) {
$message = "The IP is not valid";
}
$validator->appendMessage(
new Message($message, $attribute, "Ip")
);
return false;
}
return true;
}
}
Важно, чтобы валидаторы возвращали действительное булево значение, указывающее, была ли валидация успешной или нет.
Валидатор обратного вызова
Используя Phalcon\Validation\Validator\Callback, вы можете выполнить пользовательскую функцию, которая должна возвращать булево значение или новый класс валидатора, который будет использоваться для проверки того же поля. Возвращение true означает, что валидация успешна, а возвращение false означает, что валидация не удалась. При выполнении этого валидатора Phalcon передаст данные, в зависимости от их типа — если это сущность, будет передана сущность, в противном случае — данные. Вот пример:
use \Phalcon\Validation;
use \Phalcon\Validation\Validator\Callback;
use \Phalcon\Validation\Validator\PresenceOf;
$validation = new Validation();
$validation->add(
"amount",
new Callback(
[
"callback" => function($data) {
return $data["amount"] % 2 == 0;
},
"message" => "Only even number of products are accepted"
]
)
);
$validation->add(
"amount",
new Callback(
[
"callback" => function($data) {
if($data["amount"] % 2 == 0) {
return $data["amount"] != 2;
}
return true;
},
"message" => "You can't buy 2 products"
]
)
);
$validation->add(
"description",
new Callback(
[
"callback" => function($data) {
if($data["amount"] >= 10) {
return new PresenceOf(
[
"message" => "You must write why you need so big amount."
]
);
}
return true;
}
]
)
);
$messages = $validation->validate(["amount" => 1]); // will return message from first validator
$messages = $validation->validate(["amount" => 2]); // will return message from second validator
$messages = $validation->validate(["amount" => 10]); // will return message from validator returned by third validator
Сообщения валидации
Phalcon\Validation имеет систему сообщений, которая обеспечивает гибкий способ вывода или хранения сообщений валидации, сгенерированных во время процессов валидации.
Каждое сообщение состоит из экземпляра класса Phalcon\Validation\Message. Набор сгенерированных сообщений можно получить с помощью метода getMessages(). Каждое сообщение предоставляет расширенную информацию, например, атрибут, который сгенерировал сообщение, или тип сообщения:
$messages = $validation->validate();
if (count($messages)) {
foreach ($messages as $message) {
echo "Message: ", $message->getMessage(), "\n";
echo "Field: ", $message->getField(), "\n";
echo "Type: ", $message->getType(), "\n";
}
}
Вы можете передать параметр «message», чтобы изменить/перевести стандартное сообщение в каждом валидаторе:
use Phalcon\Validation\Validator\Email;
$validation->add(
"email",
new Email(
[
"message" => "The e-mail is not valid",
]
)
);
По умолчанию метод getMessages() возвращает все сгенерированные во время валидации сообщения. Вы можете отфильтровать сообщения для определенного поля, используя метод filter():
$messages = $validation->validate();
if (count($messages)) {
// Filter only the messages generated for the field 'name'
$filteredMessages = $messages->filter("name");
foreach ($filteredMessages as $message) {
echo $message;
}
}
Фильтрация данных
Данные могут быть отфильтрованы перед валидацией, чтобы гарантировать, что вредоносные или некорректные данные не будут проверены.
use Phalcon\Validation;
$validation = new Validation();
$validation->add(
"name",
new PresenceOf(
[
"message" => "The name is required",
]
)
);
$validation->add(
"email",
new PresenceOf(
[
"message" => "The email is required",
]
)
);
// Filter any extra space
$validation->setFilters("name", "trim");
$validation->setFilters("email", "trim");
Фильтрация и очистка выполняется с помощью компонента filter. Вы можете добавить больше фильтров в этот компонент или использовать встроенные.
События валидации
Когда валидации организованы в классах, вы можете реализовать методы beforeValidation() и afterValidation() для выполнения дополнительных проверок, фильтров, очистки и т. д. Если метод beforeValidation() возвращает false, валидация автоматически отменяется:
use Phalcon\Validation;
class LoginValidation extends Validation
{
public function initialize()
{
// ...
}
/**
* Executed before validation
*
* @param array $data
* @param object $entity
* @param Phalcon\Validation\Message\Group $messages
* @return bool
*/
public function beforeValidation($data, $entity, $messages)
{
if ($this->request->getHttpHost() !== "admin.mydomain.com") {
$messages->appendMessage(
new Message("Only users can log on in the administration domain")
);
return false;
}
return true;
}
/**
* Executed after validation
*
* @param array $data
* @param object $entity
* @param Phalcon\Validation\Message\Group $messages
*/
public function afterValidation($data, $entity, $messages)
{
// ... Add additional messages or perform more validations
}
}
Отмена валидации
По умолчанию все валидаторы, назначенные полю, проверяются независимо от того, не потерпел ли один из них неудачу. Вы можете изменить это поведение, указав валидатору, который может остановить валидацию:
use Phalcon\Validation;
use Phalcon\Validation\Validator\Regex;
use Phalcon\Validation\Validator\PresenceOf;
$validation = new Validation();
$validation->add(
"telephone",
new PresenceOf(
[
"message" => "The telephone is required",
"cancelOnFail" => true,
]
)
);
$validation->add(
"telephone",
new Regex(
[
"message" => "The telephone is required",
"pattern" => "/\+44 [0-9]+/",
]
)
);
$validation->add(
"telephone",
new StringLength(
[
"messageMinimum" => "The telephone is too short",
"min" => 2,
]
)
);
Первый валидатор имеет опцию «cancelOnFail» со значением true, поэтому если этот валидатор потерпит неудачу, оставшиеся валидаторы в цепочке не будут выполнены.
Если вы создаете пользовательские валидаторы, вы можете динамически остановить цепочку валидации, установив опцию «cancelOnFail»:
use Phalcon\Validation;
use Phalcon\Validation\Message;
use Phalcon\Validation\Validator;
class MyValidator extends Validator
{
/**
* Executes the validation
*
* @param Phalcon\Validation $validator
* @param string $attribute
* @return boolean
*/
public function validate(Validation $validator, $attribute)
{
// If the attribute value is name we must stop the chain
if ($attribute === "name") {
$this->setOption("cancelOnFail", true);
}
// ...
}
}
Избегайте проверки пустых значений
Вы можете передать опцию «allowEmpty» всем встроенным валидаторам, чтобы избежать проверки, если передано пустое значение:
use Phalcon\Validation;
use Phalcon\Validation\Validator\Regex;
$validation = new Validation();
$validation->add(
"telephone",
new Regex(
[
"message" => "The telephone is required",
"pattern" => "/\+44 [0-9]+/",
"allowEmpty" => true,
]
)
);
Рекурсивная валидация
Вы также можете запускать экземпляры Validation внутри другого через метод afterValidation(). В этом примере валидация экземпляра CompanyValidation также проверит экземпляр PhoneValidation:
use Phalcon\Validation;
class CompanyValidation extends Validation
{
/**
* @var PhoneValidation
*/
protected $phoneValidation;
public function initialize()
{
$this->phoneValidation = new PhoneValidation();
}
public function afterValidation($data, $entity, $messages)
{
$phoneValidationMessages = $this->phoneValidation->validate(
$data["phone"]
);
$messages->appendMessages(
$phoneValidationMessages
);
}
}
© 2011–2017 Phalcon Framework Team
Licensed under the Creative Commons Attribution License 3.0.
https://docs.phalconphp.com/en/latest/reference/validation.html