Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdfd8e53

Browse files
feature#59800 [Validator] Add support for closures inWhen (alexandre-daubois)
This PR was merged into the 7.3 branch.Discussion----------[Validator] Add support for closures in `When`| Q | A| ------------- | ---| Branch? | 7.3| Bug fix? | no| New feature? | yes| Deprecations? | no| Issues | -| License | MITClosures can be used instead of Expressions in the `When` constraint since PHP 8.5, like in this example:```phpuse Symfony\Component\Validator\Constraints\NotBlank;use Symfony\Component\Validator\Constraints\NotNull;use Symfony\Component\Validator\Constraints\When;class BlogPost{ #[When(expression: static function (BlogPost $subject) { return $subject->published && !$subject->draft; }, constraints: [ new NotNull(), new NotBlank(), ])] public ?string $content; public bool $published; public bool $draft;}```Commits-------f0adbea [Validator] Add support for closures in `When`
2 parents560a484 +f0adbea commitdfd8e53

File tree

6 files changed

+117
-4
lines changed

6 files changed

+117
-4
lines changed

‎src/Symfony/Component/Validator/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ CHANGELOG
1111
* Add support for the`otherwise` option in the`When` constraint
1212
* Add support for multiple fields containing nested constraints in`Composite` constraints
1313
* Add the`stopOnFirstError` option to the`Unique` constraint to validate all elements
14+
* Add support for closures in the`When` constraint
1415

1516
7.2
1617
---

‎src/Symfony/Component/Validator/Constraints/When.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,21 @@
2525
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
2626
class Whenextends Composite
2727
{
28-
publicstring|Expression$expression;
28+
publicstring|Expression|\Closure$expression;
2929
publicarray|Constraint$constraints = [];
3030
publicarray$values = [];
3131
publicarray|Constraint$otherwise = [];
3232

3333
/**
34-
* @param string|Expression|array<string,mixed>$expressionThe condition to evaluate,written with the ExpressionLanguage syntax
34+
* @param string|Expression|array<string,mixed>|\Closure(object): bool$expression The condition to evaluate,either as a closure or using the ExpressionLanguage syntax
3535
* @param Constraint[]|Constraint|null $constraints One or multiple constraints that are applied if the expression returns true
3636
* @param array<string,mixed>|null $values The values of the custom variables used in the expression (defaults to [])
3737
* @param string[]|null $groups
3838
* @param array<string,mixed>|null $options
3939
* @param Constraint[]|Constraint $otherwise One or multiple constraints that are applied if the expression returns false
4040
*/
4141
#[HasNamedArguments]
42-
publicfunction__construct(string|Expression|array$expression,array|Constraint|null$constraints =null, ?array$values =null, ?array$groups =null,$payload =null, ?array$options =null,array|Constraint$otherwise = [])
42+
publicfunction__construct(string|Expression|array|\Closure$expression,array|Constraint|null$constraints =null, ?array$values =null, ?array$groups =null,$payload =null, ?array$options =null,array|Constraint$otherwise = [])
4343
{
4444
if (!class_exists(ExpressionLanguage::class)) {
4545
thrownewLogicException(\sprintf('The "symfony/expression-language" component is required to use the "%s" constraint. Try running "composer require symfony/expression-language".',__CLASS__));

‎src/Symfony/Component/Validator/Constraints/WhenValidator.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@ public function validate(mixed $value, Constraint $constraint): void
3535
$variables['this'] =$context->getObject();
3636
$variables['context'] =$context;
3737

38-
$result =$this->getExpressionLanguage()->evaluate($constraint->expression,$variables);
38+
if ($constraint->expressioninstanceof \Closure) {
39+
$result = ($constraint->expression)($context->getObject());
40+
}else {
41+
$result =$this->getExpressionLanguage()->evaluate($constraint->expression,$variables);
42+
}
3943

4044
if ($result) {
4145
$context->getValidator()->inContext($context)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Component\Validator\Tests\Constraints\Fixtures;
13+
14+
useSymfony\Component\Validator\Constraints\NotBlank;
15+
useSymfony\Component\Validator\Constraints\NotNull;
16+
useSymfony\Component\Validator\Constraints\When;
17+
18+
#[When(expression:staticfunction () {
19+
returntrue;
20+
}, constraints:newNotNull()
21+
)]
22+
class WhenTestWithClosure
23+
{
24+
#[When(expression:staticfunction () {
25+
returntrue;
26+
}, constraints: [
27+
newNotNull(),
28+
newNotBlank(),
29+
])]
30+
private$foo;
31+
}

‎src/Symfony/Component/Validator/Tests/Constraints/WhenTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
useSymfony\Component\Validator\Mapping\ClassMetadata;
2323
useSymfony\Component\Validator\Mapping\Loader\AttributeLoader;
2424
useSymfony\Component\Validator\Tests\Constraints\Fixtures\WhenTestWithAttributes;
25+
useSymfony\Component\Validator\Tests\Constraints\Fixtures\WhenTestWithClosure;
2526

2627
finalclass WhenTestextends TestCase
2728
{
@@ -111,4 +112,38 @@ public function testAttributes()
111112
self::assertEquals([newLength(exactly:10, groups: ['foo'])],$quuxConstraint->otherwise);
112113
self::assertSame(['foo'],$quuxConstraint->groups);
113114
}
115+
116+
/**
117+
* @requires PHP 8.5
118+
*/
119+
publicfunctiontestAttributesWithClosure()
120+
{
121+
$loader =newAttributeLoader();
122+
$metadata =newClassMetadata(WhenTestWithClosure::class);
123+
124+
self::assertTrue($loader->loadClassMetadata($metadata));
125+
126+
[$classConstraint] =$metadata->getConstraints();
127+
128+
self::assertInstanceOf(When::class,$classConstraint);
129+
self::assertInstanceOf(\Closure::class,$classConstraint->expression);
130+
self::assertEquals([
131+
newCallback(
132+
callback:'callback',
133+
groups: ['Default','WhenTestWithClosure'],
134+
),
135+
],$classConstraint->constraints);
136+
self::assertEmpty($classConstraint->otherwise);
137+
138+
[$fooConstraint] =$metadata->properties['foo']->getConstraints();
139+
140+
self::assertInstanceOf(When::class,$fooConstraint);
141+
self::assertInstanceOf(\Closure::class,$fooConstraint->expression);
142+
self::assertEquals([
143+
newNotNull(groups: ['Default','WhenTestWithClosure']),
144+
newNotBlank(groups: ['Default','WhenTestWithClosure']),
145+
],$fooConstraint->constraints);
146+
self::assertEmpty($fooConstraint->otherwise);
147+
self::assertSame(['Default','WhenTestWithClosure'],$fooConstraint->groups);
148+
}
114149
}

‎src/Symfony/Component/Validator/Tests/Constraints/WhenValidatorTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,34 @@ public function testConstraintsAreExecuted()
4040
));
4141
}
4242

43+
publicfunctiontestConstraintsAreExecutedWhenClosureIsTrue()
44+
{
45+
$constraints = [
46+
newNotNull(),
47+
newNotBlank(),
48+
];
49+
50+
$this->expectValidateValue(0,'Foo',$constraints);
51+
52+
$this->validator->validate('Foo',newWhen(
53+
expression:staticfn () =>true,
54+
constraints:$constraints,
55+
));
56+
}
57+
58+
publicfunctiontestClosureTakesSubject()
59+
{
60+
$subject =new \stdClass();
61+
$this->setObject($subject);
62+
63+
$this->validator->validate($subject,newWhen(
64+
expression:staticfunction ($closureSubject)use ($subject) {
65+
self::assertSame($subject,$closureSubject);
66+
},
67+
constraints:newNotNull(),
68+
));
69+
}
70+
4371
publicfunctiontestConstraintIsExecuted()
4472
{
4573
$constraint =newNotNull();
@@ -65,6 +93,20 @@ public function testOtherwiseIsExecutedWhenFalse()
6593
));
6694
}
6795

96+
publicfunctiontestOtherwiseIsExecutedWhenClosureReturnsFalse()
97+
{
98+
$constraint =newNotNull();
99+
$otherwise =newLength(exactly:10);
100+
101+
$this->expectValidateValue(0,'Foo', [$otherwise]);
102+
103+
$this->validator->validate('Foo',newWhen(
104+
expression:staticfn () =>false,
105+
constraints:$constraint,
106+
otherwise:$otherwise,
107+
));
108+
}
109+
68110
publicfunctiontestConstraintsAreExecutedWithNull()
69111
{
70112
$constraints = [

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp