Symfony 4:如果y为null,则向x添加约束新的UniqueEntity()

时间:2019-07-02 11:22:53

标签: symfony validation doctrine constraints

我有一个具有两个属性(国家和州)的实体类。数据库中的条目必须唯一。意思是,如果我将country = Germany和state = BB提交到数据库,则如果尚不存在相同的条目,它将添加新条目。

但是,state属性可以为null,在这种情况下,不会由doctrine(?)映射,并且我仍然可以为该国家/地区提交值。问题是我无法设法使该条目唯一,即没有唯一状态的情况下,您不能多次输入相同的国家/地区。这是我挣扎的地方。

我尝试了对实体约束的各种修改。

以下是用于验证国家和州是否是数据库中唯一条目的代码:

public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addConstraint(new UniqueEntity([
            'fields' => ['country', 'state'],
            'message' => 'State is already used with this country!',
        ]));
    }

2 个答案:

答案 0 :(得分:2)

https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/tutorials/composite-primary-keys.html

也许具有复合主键的实体可以为您正常工作。

/**
 * @UniqueEntity
 */
class UniqueEntity
{
    /** @Id @Column(type="string") */
    private $country;
    /** @Id @Column(type="string") */
    private $state = 'empty'; // case you have no state and a primary key can't be null

    public function __construct($country, $state)
    {
        $this->country= $country;
        $this->state= $state;
    }

    public function getCountry()
    {
        return $this->country;
    }

    public function getState()
    {
        return $this->state;
    }
}

唯一的限制是,如果它是主键,则不能将null值用作状态,但是同样,您可以将默认值(如``no'')用作状态值,而这两者都是可接受的键还有一个独特的价值

答案 1 :(得分:0)

花了我一段时间,但这是我为解决问题而编写的自定义验证器类。也许会帮助别人。

<?php

namespace XXX;

use XXX\Services\CountryAndStateService;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class CountryAndStateValidator extends ConstraintValidator
{
/**
 * @var countryAndStateService
 */
 private $countryAndStateService;

   /**
    * CountryAndState constructor.
    */
     public function __construct(CountryAndStateService $countryAndStateService)
     {
         $this->countryAndStateService = $countryAndStateService;
     }

     /**
     * Taking country and state; validating whether the same country with state === null does already exist.
     *
     */
     public function validate($value, Constraint $constraint)
     {
        /* Accessing user input of state and country */
        $state = $this->context->getRoot()->getData()->getState();
        $country = $this->context->getRoot()->getData()->getCountry();

        /* Comparing the country user input to the country data in the database */
        $existingCountry = $this->countryAndStateService->getCountryByCountry($country);

        if ($state === null) {
            if ($existingCountry) {
                $this->context->buildViolation($constraint->message)
                    ->addViolation();
            } else {
                return;
            }
         }else {
            return;
        }
    }
}