微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

类中具有空值的唯一实体集 symfony / api-platform

如何解决类中具有空值的唯一实体集 symfony / api-platform

我有一个实体如下:

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

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

shape1: 1,1,1
shape2: 1,null,null
shape3: 1,null
shape4: 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,将在第一个空值之后触发,再次完全忽略该字段。

解决方法

您可以尝试创建一个 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();
}

然而,这不会测试是否已经存在具有相同尺寸的形状。

,

我最终按照@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();
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。