bitrix-validation
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseValidation in Bitrix
Bitrix中的验证
The service validates objects using PHP 8 attributes. Any object with typed properties can be checked to obtain a with a list of errors.
Bitrix\Main\Validation\ValidationServiceValidationResultService id in : (kernel registration). There is no section in for registering rules.
ServiceLocatormain.validation.servicevalidation.settings.phpBitrix\Main\Validation\ValidationServiceValidationResult在中的服务ID:(内核注册)。中没有用于注册规则的****配置段。
ServiceLocatormain.validation.service.settings.phpvalidationFirst-level Attributes
一级属性
| Attribute | What it checks |
|---|---|
| Not empty ( |
| String length |
| Numeric constraints |
| Numeric value >= 1 (internally |
| Format; |
| URL (no options besides |
| Regular expression (attribute name is |
| Value is one of the allowed list items; options |
| String is valid JSON |
| Recursively validate nested object; |
| Type of array elements: |
| At least one of the fields is filled (on class) |
| Exactly one of the listed fields is filled (on class) |
Each attribute accepts an optional for a custom error text (not ). For localized texts pass a instead of a string — the phrase is defined in the matching file ( is optional: when omitted it is guessed from the backtrace). Every rule also accepts ; then runs rules of that group plus all ungrouped rules; without a group everything runs.
errorMessagemessageBitrix\Main\Localization\LocalizableMessage('PHRASE_CODE', phraseSrcFile: __FILE__)lang/<code>/phraseSrcFilegroups: [...]ValidationService::validate($object, $group)Nullable handling: an uninitialized nullable property is skipped by validation; an uninitialized non-nullable property produces an error (); a property explicitly assigned counts as initialized and is passed to its validators.
MAIN_VALIDATION_EMPTY_PROPERTYnullnull| 属性 | 验证内容 |
|---|---|
| 非空( |
| 字符串长度 |
| 数值约束 |
| 数值≥1(内部基于 |
| 格式; |
| URL格式(除 |
| 正则表达式(属性名称为** |
| 值属于允许列表中的一项;可选参数 |
| 字符串为有效的JSON格式 |
| 递归验证嵌套对象; |
| 数组元素类型: |
| 至少有一个字段已填写(作用于类) |
| 恰好有一个指定字段已填写(作用于类) |
每个属性都接受可选的****参数用于自定义错误文本(不是)。如需本地化文本,可传入而非字符串——短语定义在对应的文件中(为可选参数:若省略,会通过回溯自动推断)。每个规则还支持参数;调用时,会运行该分组的规则以及所有未分组的规则;若未指定分组,则运行所有规则。
errorMessagemessageBitrix\Main\Localization\LocalizableMessage('PHRASE_CODE', phraseSrcFile: __FILE__)lang/<code>/phraseSrcFilegroups: [...]ValidationService::validate($object, $group)可空类型处理:未初始化的可空属性会被跳过验证;未初始化的非可空属性会产生错误();显式赋值为的属性视为已初始化,会被传入其验证器。
MAIN_VALIDATION_EMPTY_PROPERTYnullnullDTO with Attributes
带属性的DTO
php
<?php declare(strict_types=1);
namespace Vendor\Module\Application\Dto;
use Bitrix\Main\Validation\Rule\NotEmpty;
use Bitrix\Main\Validation\Rule\Length;
use Bitrix\Main\Validation\Rule\Email;
use Bitrix\Main\Validation\Rule\Range;
use Bitrix\Main\Validation\Rule\InArray;
final class CreateUserDto
{
public function __construct(
#[NotEmpty, Length(min: 2, max: 64)]
public readonly string $name,
#[NotEmpty, Email]
public readonly string $email,
#[Range(min: 18, max: 120)]
public readonly int $age,
#[InArray(['user', 'admin'])]
public readonly string $role,
) {}
}php
<?php declare(strict_types=1);
namespace Vendor\Module\Application\Dto;
use Bitrix\Main\Validation\Rule\NotEmpty;
use Bitrix\Main\Validation\Rule\Length;
use Bitrix\Main\Validation\Rule\Email;
use Bitrix\Main\Validation\Rule\Range;
use Bitrix\Main\Validation\Rule\InArray;
final class CreateUserDto
{
public function __construct(
#[NotEmpty, Length(min: 2, max: 64)]
public readonly string $name,
#[NotEmpty, Email]
public readonly string $email,
#[Range(min: 18, max: 120)]
public readonly int $age,
#[InArray(['user', 'admin'])]
public readonly string $role,
) {}
}Direct Validation in Service
服务中的直接验证
php
use Bitrix\Main\DI\ServiceLocator;
use Bitrix\Main\Validation\ValidationService;
final class UserService
{
private readonly ValidationService $validator;
public function __construct()
{
$this->validator = ServiceLocator::getInstance()->get('main.validation.service');
}
public function register(CreateUserDto $dto): \Bitrix\Main\Result
{
$result = new \Bitrix\Main\Result();
$validation = $this->validator->validate($dto);
if (!$validation->isSuccess())
{
foreach ($validation->getErrors() as $error)
{
// getCode() holds the property path: 'email', 'items.0.name'
$result->addError(new \Bitrix\Main\Error(
$error->getMessage(),
$error->getCode(),
));
}
return $result;
}
// ...
return $result;
}
}Or inject via / factory when registering the service, still resolving .
constructorParams'main.validation.service'php
use Bitrix\Main\DI\ServiceLocator;
use Bitrix\Main\Validation\ValidationService;
final class UserService
{
private readonly ValidationService $validator;
public function __construct()
{
$this->validator = ServiceLocator::getInstance()->get('main.validation.service');
}
public function register(CreateUserDto $dto): \Bitrix\Main\Result
{
$result = new \Bitrix\Main\Result();
$validation = $this->validator->validate($dto);
if (!$validation->isSuccess())
{
foreach ($validation->getErrors() as $error)
{
// getCode()返回属性路径:'email', 'items.0.name'
$result->addError(new \Bitrix\Main\Error(
$error->getMessage(),
$error->getCode(),
));
}
return $result;
}
// ...
return $result;
}
}也可在注册服务时通过/工厂注入,仍需解析。
constructorParams'main.validation.service'Scalar Action Parameters
标量动作参数
Rule attributes can be placed directly on controller action parameters — argument binding validates the value before the action is called:
php
use Bitrix\Main\Engine\Controller;
use Bitrix\Main\Validation\Rule\PositiveNumber;
final class User extends Controller
{
public function getAction(#[PositiveNumber] int $id): array
{
return ['id' => $id];
}
}规则属性可直接放置在控制器动作参数上——参数绑定会在调用动作之前验证值:
php
use Bitrix\Main\Engine\Controller;
use Bitrix\Main\Validation\Rule\PositiveNumber;
final class User extends Controller
{
public function getAction(#[PositiveNumber] int $id): array
{
return ['id' => $id];
}
}Request DTO in Controller (ValidationParameter
autowire)
ValidationParameter控制器中的Request DTO(ValidationParameter
自动注入)
ValidationParameterFor a set of related values create a DTO and register it via with (an AutoWire rule, not a parameter attribute). It builds the DTO through the given factory and validates it before it reaches the action; on validation errors the action is not called and the controller returns the errors.
getAutoWiredParameters()Bitrix\Main\Validation\Engine\AutoWire\ValidationParameterphp
use Bitrix\Main\Engine\Controller;
use Bitrix\Main\Validation\Engine\AutoWire\ValidationParameter;
use Vendor\Module\Application\Service\PostService;
final class Post extends Controller
{
public function getAutoWiredParameters(): array
{
return [
new ValidationParameter(
CreatePostRequest::class,
fn () => CreatePostRequest::createFromRequest($this->getRequest()),
),
];
}
public function createAction(CreatePostRequest $request, PostService $postService): array
{
// We only get here if validation was successful.
// Otherwise, the controller will return errors automatically.
$result = $postService->create($request);
if (!$result->isSuccess())
{
$this->addErrors($result->getErrors());
return [];
}
return ['id' => $result->getId()];
}
}php
namespace Vendor\Blog\Application\Request;
use Bitrix\Main\Validation\Rule\NotEmpty;
use Bitrix\Main\Validation\Rule\Length;
final class CreatePostRequest
{
public function __construct(
#[NotEmpty, Length(min: 1, max: 255)]
public readonly ?string $title = null,
public readonly ?string $body = null,
) {}
public static function createFromRequest(\Bitrix\Main\Request $request): self
{
return new self(
$request->get('title'),
$request->get('body'),
);
}
}Keep DTO properties nullable with defaults so construction from a raw request never fails — the rules (, etc.) report missing values instead.
nullNotEmptyGeneration: (Since main 25.900).
php bitrix/bitrix.php make:request CreatePost -m vendor.blog --fields=title,body对于一组相关值,可创建DTO并通过注册,使用(这是一个AutoWire规则,不是参数属性)。它会通过指定的工厂构建DTO,并在其到达动作之前进行验证;若验证失败,动作不会被调用,控制器会直接返回错误信息。
getAutoWiredParameters()Bitrix\Main\Validation\Engine\AutoWire\ValidationParameterphp
use Bitrix\Main\Engine\Controller;
use Bitrix\Main\Validation\Engine\AutoWire\ValidationParameter;
use Vendor\Module\Application\Service\PostService;
final class Post extends Controller
{
public function getAutoWiredParameters(): array
{
return [
new ValidationParameter(
CreatePostRequest::class,
fn () => CreatePostRequest::createFromRequest($this->getRequest()),
),
];
}
public function createAction(CreatePostRequest $request, PostService $postService): array
{
// 只有验证成功时才会执行到这里
// 否则控制器会自动返回错误信息
$result = $postService->create($request);
if (!$result->isSuccess())
{
$this->addErrors($result->getErrors());
return [];
}
return ['id' => $result->getId()];
}
}php
namespace Vendor\Blog\Application\Request;
use Bitrix\Main\Validation\Rule\NotEmpty;
use Bitrix\Main\Validation\Rule\Length;
final class CreatePostRequest
{
public function __construct(
#[NotEmpty, Length(min: 1, max: 255)]
public readonly ?string $title = null,
public readonly ?string $body = null,
) {}
public static function createFromRequest(\Bitrix\Main\Request $request): self
{
return new self(
$request->get('title'),
$request->get('body'),
);
}
}保持DTO属性为可空类型并设置默认值,这样从原始请求构建DTO时永远不会失败——缺失值会由规则(如)报告。
nullNotEmpty生成命令:(自main 25.900版本起支持)。
php bitrix/bitrix.php make:request CreatePost -m vendor.blog --fields=title,bodyClass-Level Attributes
类级属性
php
use Bitrix\Main\Validation\Rule\AtLeastOnePropertyNotEmpty;
#[AtLeastOnePropertyNotEmpty(['email', 'phone'])]
final readonly class ContactRequest
{
public function __construct(
public ?string $email = null,
public ?string $phone = null,
) {}
}php
use Bitrix\Main\Validation\Rule\AtLeastOnePropertyNotEmpty;
#[AtLeastOnePropertyNotEmpty(['email', 'phone'])]
final readonly class ContactRequest
{
public function __construct(
public ?string $email = null,
public ?string $phone = null,
) {}
}Collections
集合验证
php
use Bitrix\Main\Validation\Rule\Recursive\Validatable;
use Bitrix\Main\Validation\Rule\ElementsType;
final class OrderDto
{
/**
* @var OrderItemDto[]
*/
#[ElementsType(className: OrderItemDto::class)]
#[Validatable(iterable: true)]
public array $items = [];
}php
use Bitrix\Main\Validation\Rule\Recursive\Validatable;
use Bitrix\Main\Validation\Rule\ElementsType;
final class OrderDto
{
/**
* @var OrderItemDto[]
*/
#[ElementsType(className: OrderItemDto::class)]
#[Validatable(iterable: true)]
public array $items = [];
}Custom Validator
自定义验证器
There is no section. Custom rules are PHP attributes that extend and return validators from .
.settings.phpvalidationAbstractPropertyValidationAttributegetValidators()-
Attribute +:
getValidators()php<?php declare(strict_types=1); namespace Vendor\Module\Validation\Rule; use Attribute; use Bitrix\Main\Localization\LocalizableMessageInterface; use Bitrix\Main\Validation\Rule\AbstractPropertyValidationAttribute; use Bitrix\Main\Validation\Validator\ValidatorInterface; use Bitrix\Main\Validation\ValidationResult; use Bitrix\Main\Validation\ValidationError; #[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_PARAMETER)] final class EvenNumber extends AbstractPropertyValidationAttribute { public function __construct( // type must match the inherited trait property exactly protected string|LocalizableMessageInterface|null $errorMessage = null, ) {} protected function getValidators(): array { // $this->errorMessage is applied automatically by the base class // (replaceWithCustomError from ValidationErrorTrait) return [ new EvenNumberValidator(), ]; } } final class EvenNumberValidator implements ValidatorInterface { public function validate(mixed $value): ValidationResult { $result = new ValidationResult(); if (!is_int($value) || $value % 2 !== 0) { $result->addError(new ValidationError( 'Number must be even', 'EVEN_NUMBER', // the property path is prepended later: 'age.EVEN_NUMBER' failedValidator: $this, )); } return $result; } } -
Use the attribute on DTO properties — no kernel registration step:php
#[EvenNumber(errorMessage: 'Age must be even')] public readonly int $age;
ValidatorInterface::validate(mixed $value): ValidationResultRuleIn attributes extending the abstract classes, must be typed — the base declares the property with exactly this type, and PHP property types are invariant (a narrower is a fatal error). Class attributes (checks across several properties) extend / implement .
$errorMessagestring|LocalizableMessageInterface|nullValidationErrorTrait?stringAbstractClassValidationAttributeClassValidationAttributeInterface::validateObject(object $object).settings.phpvalidationAbstractPropertyValidationAttributegetValidators()-
属性 +:
getValidators()php<?php declare(strict_types=1); namespace Vendor\Module\Validation\Rule; use Attribute; use Bitrix\Main\Localization\LocalizableMessageInterface; use Bitrix\Main\Validation\Rule\AbstractPropertyValidationAttribute; use Bitrix\Main\Validation\Validator\ValidatorInterface; use Bitrix\Main\Validation\ValidationResult; use Bitrix\Main\Validation\ValidationError; #[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_PARAMETER)] final class EvenNumber extends AbstractPropertyValidationAttribute { public function __construct( // 类型必须与继承的trait属性完全匹配 protected string|LocalizableMessageInterface|null $errorMessage = null, ) {} protected function getValidators(): array { // $this->errorMessage会被基类自动应用 // (来自ValidationErrorTrait的replaceWithCustomError) return [ new EvenNumberValidator(), ]; } } final class EvenNumberValidator implements ValidatorInterface { public function validate(mixed $value): ValidationResult { $result = new ValidationResult(); if (!is_int($value) || $value % 2 !== 0) { $result->addError(new ValidationError( 'Number must be even', 'EVEN_NUMBER', // 后续会追加属性路径:'age.EVEN_NUMBER' failedValidator: $this, )); } return $result; } } -
在DTO属性上使用该属性——无需内核注册步骤:php
#[EvenNumber(errorMessage: 'Age must be even')] public readonly int $age;
ValidatorInterface::validate(mixed $value): ValidationResultRule继承抽象类的属性中,的类型必须为——基类声明的属性正是此类型,且PHP属性类型是不变的(更窄的会导致致命错误)。类级属性(跨多个属性的检查)需继承/实现。
$errorMessagestring|LocalizableMessageInterface|nullValidationErrorTrait?stringAbstractClassValidationAttributeClassValidationAttributeInterface::validateObject(object $object)Retrieving Validation Result
获取验证结果
ValidationResultBitrix\Main\ResultValidationErrorBitrix\Main\Error- : localized message.
getMessage() - : property path that failed — the service prefixes the property name (and array index for iterables), e.g.
getCode(),email; a code set inside a validator is appended after a dot (items.0.name).age.EVEN_NUMBER - : the
getFailedValidator()instance that produced the error (orValidatorInterface).null
There is no method — the field name lives in the code.
getField()ValidationResultBitrix\Main\ResultValidationErrorBitrix\Main\Error- :本地化消息。
getMessage() - :验证失败的属性路径——服务会添加属性名称(以及数组的索引),例如
getCode()、email;验证器内部设置的代码会以点号追加在后面(如items.0.name)。age.EVEN_NUMBER - :产生错误的
getFailedValidator()实例(或ValidatorInterface)。null
没有方法——字段名称包含在错误代码中。
getField()Checklist
检查清单
- Validation is handled via PHP 8 attributes.
- DTOs are used for complex input structures.
- Request DTOs are wired via in
ValidationParameter; scalar action params carry rule attributes directly.getAutoWiredParameters() - DTO properties are nullable with defaults; remember: uninitialized nullable props are skipped, explicit
nullis validated.null - Custom rules extend and implement
AbstractPropertyValidationAttribute— nogetValidators().settings.phpsection.validation - Attribute names use /
RegExp(noterrorMessage/Regex).message - is retrieved as
ValidationService.main.validation.service - Error messages are localized or descriptive.
- Collections of DTOs are validated with +
#[ElementsType(className: ...)].#[Validatable(iterable: true)]
- 验证通过PHP 8属性实现。
- 使用DTO处理复杂输入结构。
- Request DTO通过中的
getAutoWiredParameters()注入;标量动作参数直接携带规则属性。ValidationParameter - DTO属性为可空类型并设置默认值;注意:未初始化的可空属性会被跳过验证,显式赋值的
null会被验证。null - 自定义规则继承并实现
AbstractPropertyValidationAttribute——无需getValidators()中的.settings.php配置段。validation - 属性名称使用/
RegExp(而非errorMessage/Regex)。message - 通过获取
main.validation.service。ValidationService - 错误消息已本地化或描述清晰。
- DTO集合通过+
#[ElementsType(className: ...)]进行验证。#[Validatable(iterable: true)]