├── .github
├── FUNDING.yml
└── workflows
│ ├── ci.yml
│ └── static.yml
├── phpstan.neon.dist
├── psalm.xml
├── composer.json
├── src
├── EntityExist.php
└── EntityExistValidator.php
├── phpunit.xml.dist
├── LICENSE
└── Readme.md
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [Nyholm]
4 |
--------------------------------------------------------------------------------
/phpstan.neon.dist:
--------------------------------------------------------------------------------
1 | #includes:
2 | # - phpstan-baseline.neon
3 |
4 | parameters:
5 | level: 5
6 | reportUnmatchedIgnoredErrors: false
7 | paths:
8 | - src
9 |
--------------------------------------------------------------------------------
/psalm.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "happyr/entity-exists-validation-constraint",
3 | "description": "Verify that your entity exists",
4 | "license": "MIT",
5 | "type": "library",
6 | "authors": [
7 | {
8 | "name": "Radoje Albijanic",
9 | "email": "radoje.albijanic@gmail.com"
10 | },
11 | {
12 | "name": "Tobias Nyholm",
13 | "email": "tobias.nyholm@gmail.com"
14 | }
15 | ],
16 | "require": {
17 | "php": "^8.1",
18 | "doctrine/orm": "^2.4 || ^3.0",
19 | "symfony/validator": "^6.0 || ^7.0"
20 | },
21 | "require-dev": {
22 | "symfony/phpunit-bridge": "^6.0",
23 | "symfony/validator": "^6.4 || ^7.0"
24 | },
25 | "autoload": {
26 | "psr-4": {
27 | "Happyr\\Validator\\Constraint\\": "src/"
28 | }
29 | },
30 | "autoload-dev": {
31 | "psr-4": {
32 | "Tests\\Happyr\\Validator\\Constraint\\": "tests/"
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/EntityExist.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | #[\Attribute(\Attribute::TARGET_PROPERTY)]
15 | final class EntityExist extends Constraint
16 | {
17 | public $message = 'Entity "%entity%" with property "%property%": "%value%" does not exist.';
18 | public $property = 'id';
19 | public $entity;
20 |
21 | public function __construct($entity = null, $property = null, $message = null, $options = null, array $groups = null, $payload = null)
22 | {
23 | parent::__construct($options, $groups, $payload);
24 |
25 | $this->entity = $entity ?? $this->entity;
26 | $this->property = $property ?? $this->property;
27 | $this->message = $message ?? $this->message;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | ./tests
21 |
22 |
23 |
24 |
25 |
26 | ./
27 |
28 | vendor
29 | tests
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019 Happyr
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Tests
2 | on: [ pull_request ]
3 |
4 | jobs:
5 | phpunit:
6 | name: PHPUnit
7 | runs-on: ubuntu-latest
8 | strategy:
9 | max-parallel: 10
10 | matrix:
11 | versions:
12 | - sf: '6.4.*'
13 | php: '8.1'
14 | - sf: '6.4.*'
15 | php: '8.2'
16 | - sf: '6.4.*'
17 | php: '8.3'
18 | - sf: '7.1.*'
19 | php: '8.2'
20 | - sf: '7.1.*'
21 | php: '8.3'
22 |
23 | steps:
24 | - name: Set up PHP
25 | uses: shivammathur/setup-php@2.7.0
26 | with:
27 | php-version: ${{ matrix.versions.php }}
28 | coverage: none
29 | tools: flex
30 |
31 | - name: Checkout code
32 | uses: actions/checkout@v2
33 |
34 | - name: Download dependencies
35 | env:
36 | SYMFONY_REQUIRE: ${{ matrix.versions.sf }}
37 | uses: ramsey/composer-install@v1
38 |
39 | - name: Run tests
40 | run: ./vendor/bin/simple-phpunit
41 |
42 | lowest:
43 | name: Lowest deps
44 | runs-on: ubuntu-latest
45 | steps:
46 | - name: Set up PHP
47 | uses: shivammathur/setup-php@2.5.0
48 | with:
49 | php-version: 8.3
50 | coverage: none
51 |
52 | - name: Checkout code
53 | uses: actions/checkout@v2
54 |
55 | - name: Download dependencies
56 | with:
57 | dependency-versions: "lowest"
58 | uses: ramsey/composer-install@v1
59 |
60 | - name: Run tests
61 | env:
62 | SYMFONY_DEPRECATIONS_HELPER: "max[self]=0"
63 | run: ./vendor/bin/simple-phpunit
64 |
--------------------------------------------------------------------------------
/src/EntityExistValidator.php:
--------------------------------------------------------------------------------
1 |
13 | * @author Radoje Albijanic
14 | */
15 | final class EntityExistValidator extends ConstraintValidator
16 | {
17 | private $entityManager;
18 |
19 | public function __construct(EntityManagerInterface $entityManager)
20 | {
21 | $this->entityManager = $entityManager;
22 | }
23 |
24 | public function validate($value, Constraint $constraint): void
25 | {
26 | if (!$constraint instanceof EntityExist) {
27 | throw new \LogicException(\sprintf('You can only pass %s constraint to this validator.', EntityExist::class));
28 | }
29 |
30 | if (null === $value || '' === $value) {
31 | return;
32 | }
33 |
34 | if (empty($constraint->entity)) {
35 | throw new \LogicException(\sprintf('Must set "entity" on "%s" validator', EntityExist::class));
36 | }
37 |
38 | $data = $this->entityManager->getRepository($constraint->entity)->findOneBy([
39 | $constraint->property => $value,
40 | ]);
41 |
42 | if (null === $data) {
43 | $this->context->buildViolation($constraint->message)
44 | ->setParameter('%entity%', $constraint->entity)
45 | ->setParameter('%property%', $constraint->property)
46 | ->setParameter('%value%', (string) $value)
47 | ->addViolation();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/.github/workflows/static.yml:
--------------------------------------------------------------------------------
1 | on: [pull_request]
2 | name: Static analysis
3 |
4 | jobs:
5 | phpstan:
6 | name: PHPStan
7 | runs-on: ubuntu-20.04
8 |
9 | steps:
10 | - name: Checkout code
11 | uses: actions/checkout@v2
12 |
13 | - name: Setup PHP
14 | uses: shivammathur/setup-php@v2
15 | with:
16 | php-version: 8.3
17 | coverage: none
18 | tools: phpstan:0.12.92, cs2pr
19 |
20 | - name: Download dependencies
21 | uses: ramsey/composer-install@v1
22 |
23 | - name: PHPStan
24 | run: phpstan analyze --no-progress --error-format=checkstyle | cs2pr
25 |
26 | php-cs-fixer:
27 | name: PHP-CS-Fixer
28 | runs-on: ubuntu-20.04
29 |
30 | steps:
31 | - name: Checkout code
32 | uses: actions/checkout@v2
33 |
34 | - name: Setup PHP
35 | uses: shivammathur/setup-php@v2
36 | with:
37 | php-version: 8.0
38 | coverage: none
39 | tools: php-cs-fixer:2.19.0, cs2pr
40 |
41 | - name: PHP-CS-Fixer
42 | run: php-cs-fixer fix --dry-run --format=checkstyle | cs2pr
43 |
44 | psalm:
45 | name: Psalm
46 | runs-on: ubuntu-20.04
47 | steps:
48 | - name: Checkout code
49 | uses: actions/checkout@v2
50 |
51 | - name: Setup PHP
52 | uses: shivammathur/setup-php@v2
53 | with:
54 | php-version: 8.3
55 | coverage: none
56 | tools: vimeo/psalm:5.24.0
57 |
58 | - name: Download dependencies
59 | uses: ramsey/composer-install@v1
60 |
61 | - name: Psalm
62 | run: psalm --no-progress --output-format=github
63 |
64 | composer-normalize:
65 | name: Composer Normalize
66 | runs-on: ubuntu-20.04
67 |
68 | steps:
69 | - name: Setup PHP
70 | uses: shivammathur/setup-php@v2
71 | with:
72 | php-version: 8.3
73 | coverage: none
74 | tools: composer-normalize
75 |
76 | - name: Checkout code
77 | uses: actions/checkout@v2
78 |
79 | - name: Normalize
80 | run: composer-normalize --dry-run
81 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # Symfony validator for Entity Exist
2 |
3 | [](https://github.com/happyr/entity-exists-validation-constraint/releases)
4 | [](LICENSE)
5 | [](https://travis-ci.org/happyr/entity-exists-validation-constraint)
6 | [](https://scrutinizer-ci.com/g/happyr/entity-exists-validation-constraint)
7 | [](https://scrutinizer-ci.com/g/happyr/entity-exists-validation-constraint)
8 | [](https://packagist.org/packages/happyr/entity-exists-validation-constraint)
9 |
10 | A small validator that verifies that an Entity actually exists. This is especially useful if you use Symfony Messenger
11 | component. Now you can safely validate the message and put it on a queue for processing later.
12 |
13 |
14 | ```php
15 | namespace App\Message\Command;
16 |
17 | use Happyr\Validator\Constraint\EntityExist;
18 | use Symfony\Component\Validator\Constraints as Assert;
19 |
20 | final class EmailUser
21 | {
22 | /**
23 | * @Assert\NotBlank
24 | * @EntityExist(entity="App\Entity\User")
25 | *
26 | * @var int User's id property
27 | */
28 | private $user;
29 |
30 | /**
31 | * @Assert\NotBlank
32 | * @EntityExist(entity="App\Entity\Other", property="name")
33 | *
34 | * @var string The name of "Other". We use its "name" property.
35 | */
36 | private $other;
37 |
38 | // ...
39 | ```
40 |
41 | In case you are using other constraints to validate the property before entity should be checked in the database (like `@Assert\Uuid`) you should use [Group sequence](https://symfony.com/doc/current/validation/sequence_provider.html) in order to avoid 500 errors from Doctrine mapping.
42 |
43 | ```php
44 | namespace App\Message\Command;
45 |
46 | use Happyr\Validator\Constraint\EntityExist;
47 | use Symfony\Component\Validator\Constraints as Assert;
48 |
49 | /**
50 | * @Assert\GroupSequence({"EmailUser", "DatabaseCall"})
51 | */
52 | final class EmailUser
53 | {
54 | /**
55 | * @Assert\NotBlank
56 | * @Assert\Uuid
57 | * @EntityExist(entity="App\Entity\User", groups={"DatabaseCall"}, property="uuid")
58 | *
59 | * @var string Uuid
60 | */
61 | private $user;
62 |
63 | // ...
64 | ```
65 |
66 | ## Install
67 |
68 | ```console
69 | composer require happyr/entity-exists-validation-constraint
70 |
71 | ```
72 |
73 | Then register the services with:
74 |
75 | ```yaml
76 | # config/packages/happyr_entity_exists_validator.yaml
77 | services:
78 | Happyr\Validator\Constraint\EntityExistValidator:
79 | arguments: ['@doctrine.orm.entity_manager']
80 | tags: [ 'validator.constraint_validator' ]
81 | ```
82 |
83 | ## Note
84 |
85 | The Validator will not produce a violation when value is empty. This means that you should most likely use it in
86 | combination with `NotBlank`.
87 |
--------------------------------------------------------------------------------