我有一个具有两个属性(国家和州)的实体类。数据库中的条目必须唯一。意思是,如果我将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!',
]));
}
答案 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;
}
}
}