How to validate unique entities in an entity collection in symfony2

后端 未结 4 614
心在旅途
心在旅途 2020-12-29 09:46

I have an entity with a OneToMany relation to another entity, when I persist the parent entity I want to ensure the children contain no duplicates.

Here\'s the class

4条回答
  •  南笙
    南笙 (楼主)
    2020-12-29 10:35

    For Symfony 4.3(only tested version) you can use my custom validator. Prefered way of usage is as annotaion on validated collection:

    use App\Validator\Constraints as App;
    

    ...

    /**
     * @ORM\OneToMany
     *
     * @App\UniqueProperty(
     *     propertyPath="entityProperty"
     * )
     */
    private $entities;
    

    Difference between Julien and my solution is, that my Constraint is defined on validated Collection instead on element of Collection itself.

    Constraint:

    #src/Validator/Constraints/UniqueProperty.php
    

    Validator:

    #src/Validator/Constraints/UniquePropertyValidator.php
    propertyAccessor = PropertyAccess::createPropertyAccessor();
        }
    
        /**
         * @param mixed $value
         * @param Constraint $constraint
         * @throws \Exception
         */
        public function validate($value, Constraint $constraint)
        {
            if (!$constraint instanceof UniqueProperty) {
                throw new UnexpectedTypeException($constraint, UniqueProperty::class);
            }
    
            if (null === $value) {
                return;
            }
    
            if (!\is_array($value) && !$value instanceof \IteratorAggregate) {
                throw new UnexpectedValueException($value, 'array|IteratorAggregate');
            }
    
            if ($constraint->propertyPath === null) {
                throw new \Exception('Option propertyPath can not be null');
            }
    
            $propertyValues = [];
            foreach ($value as $key => $element) {
                $propertyValue = $this->propertyAccessor->getValue($element, $constraint->propertyPath);
                if (in_array($propertyValue, $propertyValues, true)) {
                    $this->context->buildViolation($constraint->message)
                        ->atPath(sprintf('[%s]', $key))
                        ->addViolation();
                }
    
                $propertyValues[] = $propertyValue;
            }
        }
    }
    

提交回复
热议问题