Skip to content

Commit fb23eef

Browse files
committed
feature #38662 [DoctrineBridge][Validator] Allow validating every class against unique entity constraint (wkania)
This PR was merged into the 7.1 branch. Discussion ---------- [DoctrineBridge][Validator] Allow validating every class against unique entity constraint | Q | A | ------------- | --- | Branch? | 7.x <!-- see below --> | Bug fix? | no | New feature? | yes <!-- pleasedate src/**/CHANGELOG.md files --> | Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Tickets | Fix #22592 | License | MIT | Doc PR | symfony/symfony-docs#14458 <!-- required for new features --> Yet another try to allow validating every class against unique entity constraint. Based on the knowledge from issue symfony/symfony#22592 and pull request symfony/symfony#24974. This constraint doesn’t provide any protection against race conditions, which is enough in most cases. You can always try-catch flush method. Let's not talk about this problem. Current state: - can be applied only to an entity, - support entity inheritance, - can validate unique combinations of multiple fields, - meaningful errors related to entities, - is valid during an update, when the only matched entity is the same as the entity being validated New state: - preserve the current state, - all old tests pass (no changes in them), - no breaking changes, - can be applied to any class (like DTO), - can map object fields to entity fields (optional), - when the object update some entity, there is an option to provide the identifier field names to match that entity (optional) Examples: 1. DTO adds a new entity. ``` namespace App\Message; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; /** * `@UniqueEntity`(fields={"name"}, entityClass="App\Entity\User") */ class HireAnEmployee { public $name; public function __construct($name) { $this->name = $name; } } ``` 2. DTO adds a new entity, but the name of the field in the entity is different. ``` namespace App\Message; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; /** * `@UniqueEntity`(fields={"name": "username"}, entityClass="App\Entity\User") */ class HireAnEmployee { public $name; public function __construct($name) { $this->name = $name; } } ``` 3. DTO updates an entity. ``` namespace App\Message; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; /** * `@UniqueEntity`(fields={"name"}, entityClass="App\Entity\User", identifierFieldNames={"uid": "id"}) */ class UpdateEmployeeProfile { public $uid; public $name; public function __construct($uid, $name) { $this->uid = $uid; $this->name = $name; } } ``` Commits ------- adb9afa4a5 [DoctrineBridge][Validator] Allow validating every class against unique entity constraint
2 parents 9d68907 + 29f1511 commit fb23eef

10 files changed

+490
-22
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ CHANGELOG
77
* Deprecate the `DoctrineExtractor::getTypes()` method, use `DoctrineExtractor::getType()` instead
88
* Allow `EntityValueResolver` to return a list of entities
99
* Add support for auto-closing idle connections
10+
* Allow validating every class against `UniqueEntity` constraint
1011

1112
7.0
1213
---
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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+
namespace Symfony\Bridge\Doctrine\Tests\Fixtures;
13+
14+
class CreateDoubleNameEntity
15+
{
16+
public $primaryName;
17+
public $secondaryName;
18+
19+
public function __construct($primaryName, $secondaryName)
20+
{
21+
$this->primaryName = $primaryName;
22+
$this->secondaryName = $secondaryName;
23+
}
24+
}

Tests/Fixtures/Dto.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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+
namespace Symfony\Bridge\Doctrine\Tests\Fixtures;
13+
14+
class Dto
15+
{
16+
public string $foo;
17+
}

Tests/Fixtures/HireAnEmployee.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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+
namespace Symfony\Bridge\Doctrine\Tests\Fixtures;
13+
14+
class HireAnEmployee
15+
{
16+
public $name;
17+
18+
public function __construct($name)
19+
{
20+
$this->name = $name;
21+
}
22+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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+
namespace Symfony\Bridge\Doctrine\Tests\Fixtures;
13+
14+
class UpdateCompositeIntIdEntity
15+
{
16+
public $id1;
17+
public $id2;
18+
public $name;
19+
20+
public function __construct($id1, $id2, $name)
21+
{
22+
$this->id1 = $id1;
23+
$this->id2 = $id2;
24+
$this->name = $name;
25+
}
26+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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+
namespace Symfony\Bridge\Doctrine\Tests\Fixtures;
13+
14+
class UpdateCompositeObjectNoToStringIdEntity
15+
{
16+
/**
17+
* @var SingleIntIdNoToStringEntity
18+
*/
19+
protected $object1;
20+
21+
/**
22+
* @var SingleIntIdNoToStringEntity
23+
*/
24+
protected $object2;
25+
26+
public $name;
27+
28+
public function __construct(SingleIntIdNoToStringEntity $object1, SingleIntIdNoToStringEntity $object2, $name)
29+
{
30+
$this->object1 = $object1;
31+
$this->object2 = $object2;
32+
$this->name = $name;
33+
}
34+
35+
public function getObject1(): SingleIntIdNoToStringEntity
36+
{
37+
return $this->object1;
38+
}
39+
40+
public function getObject2(): SingleIntIdNoToStringEntity
41+
{
42+
return $this->object2;
43+
}
44+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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+
namespace Symfony\Bridge\Doctrine\Tests\Fixtures;
13+
14+
class UpdateEmployeeProfile
15+
{
16+
public $id;
17+
public $name;
18+
19+
public function __construct($id, $name)
20+
{
21+
$this->id = $id;
22+
$this->name = $name;
23+
}
24+
}

0 commit comments

Comments
 (0)