我有一个自定义约束验证程序( @AssertUniquePhoneNumber()),用于检查客户端实体的$ phone和$ second_phone字段中是否重复了电话号码。
class Client {
/**
* @ORM\Column(name="phone", type="phone_number", length=50, nullable=true)
* @AssertPhoneNumber(type="any")
* @AssertUniquePhoneNumber()
*/
protected $phone = null;
/**
* @ORM\Column(name="second_phone", type="phone_number", length=50, nullable=true)
* @AssertPhoneNumber(type="any")
* @AssertUniquePhoneNumber()
*/
protected $second_phone = null;
创建新客户端时,它可以正常运行,但编辑/更新客户端时会出现问题,导致无效的电话限制违规。
这是控制器:
/**
* @Route("/comercial/clients/edit_client/{clientId}",
* requirements={"id" = "\d+"},
* defaults={"id" = 1},
* name="comercial_dashboard.clients.edit_client")
*/
public function comercialEditClient(Request $request, $clientId) {
$repository = $this->getDoctrine()->getRepository('App:Client');
$client = $repository->findOneById($clientId);
if (!$client) {
throw $this->createNotFoundException(
'Cliente no encontrado con id ' . $clientId . '.'
);
}
$form = $this->createForm(EditClientFormType::class, $client);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$client = $form->getData();
$client->setUpdatedAt(new \DateTime('now'));
$em = $this->getDoctrine()->getManager();
$em->persist($client);
$em->flush();
}
这是验证者:
class UniquePhoneNumberValidator extends ConstraintValidator {
private $em;
public function __construct(EntityManagerInterface $entityManager) {
$this->em = $entityManager;
}
public function validate($phoneNumber, Constraint $constraint) {
// check if null
if (null === $phoneNumber || '' === $phoneNumber) {
return;
}
$repository = $this->em->getRepository('App:Client');
$client = $repository->findByPhoneNumber($phoneNumber);
if (!is_null($client)) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ phoneNumber }}', $phoneNumber)
->addViolation();
}
}
}
这是约束函数:
// unique phone number constraint function
public function findByPhoneNumber(PhoneNumber $phoneNumber) {
$phoneUtil = PhoneNumberUtil::getInstance();
$qb = $this->getEntityManager()->createQueryBuilder('c');
$qb->select('c')
->from('App:Client', 'c')
->where($qb->expr()->orX(
$qb->expr()->eq('c.phone', ':phone'), $qb->expr()->eq('c.second_phone', ':phone')
))
->setParameter('phone', $phoneUtil->format($phoneNumber, PhoneNumberFormat::E164))
->setMaxResults(1);
return $qb->getQuery()->getOneOrNullResult();
}
如何在编辑/更新客户端时告诉应用不验证电话字段?
答案 0 :(得分:1)
正如您可能也想到的那样,您的问题是,在编辑客户端实体时,您的存储库查询会返回数据库中已存在这些语音库(因为它们存储在当前编辑的内容中),因此您的验证器返回验证违规。
我的第一个答案是,这看起来像你应该使用类验证器而不是通用约束验证器,因为验证器在任何情况下都只检查客户端实体电话号码。因此,使用类验证器,您需要修改验证类&稍微注释并单独检查每个电话号码,并将实体ID传递给存储库函数以从查询中排除。
如果由于某种原因您更喜欢使用此方法,则可以从约束验证函数访问实体,因此您也可以在此处获取实体ID并将其传递给存储库函数。
public function validate($phoneNumber, Constraint $constraint) {
// check if null
if (null === $phoneNumber || '' === $phoneNumber) {
return;
}
$currentObject = $this->context->getObject();
$repository = $this->em->getRepository('App:Client');
$client = $repository->findByPhoneNumber($phoneNumber, $currentObject);
if (!is_null($client)) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ phoneNumber }}', $phoneNumber)
->addViolation();
}
}
如上所述,无论您是使用类验证器还是通用约束验证器,都需要更新存储库函数以从搜索中排除当前客户端实体ID。
答案 1 :(得分:0)
您可以使用validation groups。
在注释的约束中添加组:
/**
* @ORM\Column(name="phone", type="phone_number", length=50, nullable=true)
* @AssertPhoneNumber(type="any")
* @AssertUniquePhoneNumber(groups={"creation"})
*/
protected $phone = null;
/**
* @ORM\Column(name="second_phone", type="phone_number", length=50, nullable=true)
* @AssertPhoneNumber(type="any")
* @AssertUniquePhoneNumber(groups={"creation"})
*/
protected $second_phone = null;
/**
* @ORM\Column(name="email", type="string", length=255)
* @Assert\NotBlank(groups={"creation", "edition"})
*/
protected $email;
然后定义构建表单时用于验证的约束,这取决于您创建表单的方式。 The documentation给出了以下示例。
在控制器中:
$form = $this->createFormBuilder($users, array(
'validation_groups' => array('creation'),
))->add(...);
在表单类中:
use Symfony\Component\OptionsResolver\OptionsResolver;
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => array('creation'),
));
}