【问题标题】:Unique set of Entities in class with null values symfony / api-platform类中具有空值的唯一实体集 symfony / api-platform
【发布时间】:2021-02-09 16:57:17
【问题描述】:

我有一个实体如下:

 shape
 --------------
 ?float height
 ?float width
 ?float depth

我想将对象的创建限制为唯一值,包括空值的组合 例如:

shape1: 1,1,1
shape2: 1,null,null
shape3: 1,1,null
shape4: null,null,null
... 

我已尝试添加 UniqueEntity 约束来执行此操作:

* @UniqueEntity(
*     fields={"height","width","depth"}
* )

但只有在传递实际值时才会触发验证:

 id    height    width    depth
 1       1         1        1    <- triggers constraint if inserted twice
 2       1       null     null   <- does not trigger constraint if inserted twice
 3     null      null     null   <- does not trigger constraint if inserted twice
 4       1         1      null   <- triggers constraint if inserted twice

我该如何解决这个问题? ignoreNull 将完全忽略空值,或者,如果设置为 =false,将在第一个空值之后触发,再次完全忽略该字段。

【问题讨论】:

    标签: symfony api-platform.com


    【解决方案1】:

    您可以尝试创建Class Constraint Validator。其中可能有类似的内容:

    public function validate($shape, Constraint $constraint)
    {
        $same = false;
        $nulls = is_null($shape->getHeight()) + is_null($shape->getWidth()) + is_null($shape->getDepth());
        if ($shape->getHeight() === $shape->getWidth() || $shape->getHeight() === $shape->getDepth() || $shape->getWidth() === $shape->getDepth()) {
            $same = true;
        }
        if ($nulls > 1 || !$same) {
            return;
        }
        $this->context->buildViolation($constraint->message)
                ->atPath('foo')
                ->addViolation();
    }
    
    

    但是,这并不能测试是否已经存在具有相同尺寸的形状。

    【讨论】:

    • 感谢您的回复。我最终像你说的那样创建了一个类约束验证器,然后循环遍历类的属性。我将用它创建一个答案
    【解决方案2】:

    我最终按照@geoB 的建议创建了一个类约束验证器:

    <?php
    
    namespace App\Validator\Constraints;
    
    use Doctrine\Common\Persistence\ManagerRegistry;
    use Symfony\Component\Validator\Constraint;
    use Symfony\Component\Validator\ConstraintValidator;
    
    // https://symfony.com/doc/current/validation/custom_constraint.html
    class RequiresUniqueEntityValidator extends ConstraintValidator
    {
        /**
         * @var ManagerRegistry
         */
        private ManagerRegistry $managerRegistry;
    
        public function __construct(
            ManagerRegistry $managerRegistry
        )
        {
            $this->managerRegistry = $managerRegistry;
        }
    
        public function validate($value, Constraint $constraint)
        {
            $repository = $this->managerRegistry->getRepository(get_class($value));
            $reflection = new \ReflectionClass($value);
            $properties = $reflection->getProperties();
            $items = [];
            foreach ($properties as $property) {
                $propertyValue = $value->{"get" . ucfirst($property->name)}();
                $items[$property->name] = $propertyValue;
            }
            $result = $repository->findBy($items);
            if (count($result) > 0) {
                // if an item was found, that means that it already exists -> raise Violation
                }
                $text = 'The Item with fields: is not unique';
                $this->context
                    ->buildViolation($constraint->message)
                    ->setParameter('{{ notUnique }}', $text)
                    ->atPath(get_class($value))
                    ->addViolation();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-09
      • 1970-01-01
      • 2016-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-30
      相关资源
      最近更新 更多