Новое в Symfony 7.2: Улучшение составных ограничений

Источник: «New in Symfony 7.2: Compound Constraint Improvements»
В Symfony 7.2 составные ограничения легче тестировать и можно определять группы валидации и полезную нагрузку через конструктор.

Составное ограничение позволяет группировать другие ограничения в одно многократно используемое ограничение, позволяющее применять одну и ту же валидацию в разных частях приложения. Например, можно проверить политику паролей, проверив все условия с помощью такого набора ограничений:

// src/Validator/MatchPasswordPolicy.php
use Symfony\Component\Validator\Constraints as Assert;

#[\Attribute]
class MatchPasswordPolicy extends Assert\Compound
{
protected function getConstraints(array $options): array
{
return [
new Assert\NotBlank(allowNull: false),
new Assert\Length(min: 8, max: 255),
new Assert\NotCompromisedPassword(),
new Assert\Type('string'),
new Assert\Regex('/[A-Z]+/'),
// ...
];
}
}

Затем в сущности User можно применить это составное ограничение следующим образом:

// src/Entity/User.php
namespace App\Entity\User;

use App\Validator\Constraints as Assert;

class User
{
#[Assert\MatchPasswordPolicy]
public string $plainPassword;

// ...
}

В Symfony 7.2 были добавлены несколько возможностей для упрощения работы с составными ограничениями.

Более простые тесты составных ограничений

Раньше тестирование составных ограничений было неоправданно сложным. Поэтому для облегчения тестирования мы вводим новый класс CompoundConstraintTestCase. Это абстрактный класс, требующий определения единственного метода:

abstract class CompoundConstraintTestCase extends TestCase
{
abstract protected function createCompound(): Compound;

// ...
}

Используя самое составное ограничение MatchPasswordPolicy, продемонстрированное ранее, можно написать тест для него следующим образом:

// tests/Validator/MatchPasswordPolicyTest.php
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Test\CompoundConstraintTestCase;

class MatchPasswordPolicyTest extends CompoundConstraintTestCase
{
public function createCompound(): Assert\Compound
{
return new MatchPasswordPolicy();
}

/**
* @dataProvider provideInvalidPasswords
*/

public function testInvalid(mixed $password, string $code): void
{
$this->validateValue($password);

$this->assertViolationIsRaisedByCompound($code);
}

public static function provideInvalidPasswords(): \Generator
{
yield 'Blank' => ['', Assert\NotBlank::IS_BLANK_ERROR];
yield 'Too short' => ['a', Assert\Length::TOO_SHORT_ERROR];
yield 'Not a string' => [1, Assert\Type::INVALID_TYPE_ERROR];
// ...
}

public function testValid(): void
{
$this->validateValue('VeryStr0ngP4$$wOrD');

$this->assertNoViolation();
}
}

Добавление аргументов конструктора $groups и $payload

Недавно мы добавили аргументы $groups и $payload в конструктор многих составных ограничений, но не добавили их в составное ограничение. В Symfony 7.2 мы добавили эти аргументы, чтобы их можно было передавать в конструктор:

class User
{
#[Assert\MatchPasswordPolicy(
groups: ['registration'],
payload: ['severity' => 'error'],
)
]

public string $plainPassword;

// ...
}

Комментарии


Дополнительные материалы

Предыдущая Статья

Как использовать Pan для простой аналитики в приложении Laravel

Следующая Статья

Понимание разницы между объектами File и Blob