Php Symfony表单约束验证器和编辑/更新冲突
我有一个自定义约束验证器(@AssertUniquePhoneNumber()),用于检查客户端实体的$phone和$second\u phone字段中是否重复了电话号码Php Symfony表单约束验证器和编辑/更新冲突,php,symfony,Php,Symfony,我有一个自定义约束验证器(@AssertUniquePhoneNumber()),用于检查客户端实体的$phone和$second\u phone字段中是否重复了电话号码 class Client { /** * @ORM\Column(name="phone", type="phone_number", length=50, nullable=true) * @AssertPhoneNumber(type="any") * @AssertUniquePh
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();
}
$form = $this->createFormBuilder($users, array(
'validation_groups' => array('creation'),
))->add(...);
这是验证器:
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();
}
在编辑/更新客户机时,我如何告诉应用程序不要验证电话字段?由于您可能也有困惑,您的问题是,在编辑客户机实体时,存储库查询返回这些电话号码已经存在于数据库中(因为它们是为当前编辑的条目存储的),因此您的验证器返回验证冲突 我的第一个答案是,您应该使用类验证器而不是通用约束验证器,因为您的验证器在任何情况下都只检查客户实体电话号码。因此,使用类验证器,您需要稍微修改验证类和注释,并检查每个电话号码另外,将实体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。您可以使用
将组添加到注释中的约束:
/**
* @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;
然后定义在构建表单时用于验证的约束,这取决于创建表单的方式。
给出以下示例
在控制器中:
/**
* @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();
}
$form = $this->createFormBuilder($users, array(
'validation_groups' => array('creation'),
))->add(...);
在form类中:
use Symfony\Component\OptionsResolver\OptionsResolver;
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => array('creation'),
));
}
也许你忘记接受上一个问题的答案了?@gp\u sflover抱歉,我不知道这个功能。它现在已经完成了。做得好,不用担心,只是提醒你要帮忙:-)谢谢,我会试试,它看起来更干净。实际上,它严格地回答了你的问题“我如何告诉应用程序在编辑时不要验证电话字段。”但您真的要禁用编辑验证吗?如果号码已更改,您仍要检查数据库中是否不存在新号码。。。