How to validate unique entities in an entity collection in symfony2

后端 未结 4 608
心在旅途
心在旅途 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条回答
  •  旧时难觅i
    2020-12-29 10:30

    Here is a version working with multiple fields just like UniqueEntity does. Validation fails if multiple objects have same values.

    Usage:

    /**
    * ....
    * @App\UniqueInCollection(fields={"name", "email"})
    */
    private $contacts;
    //Validation fails if multiple contacts have same name AND email
    

    The constraint class ...

    The validator itself ....

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

提交回复
热议问题