我在Symfony2中遇到验证系统问题。我有一个帐户实体,经过注册和帐户更新验证。该实体具有用户名,密码,姓名,电子邮件等。在“帐户更新”屏幕上,我允许更新帐户的用户名和密码。我希望只有输入一个值才能在帐户上更新密码,这样可以很好地实现,但验证失败,因为Validator需要密码。如果我使用密码和帐户注册一个单独的组而没有密码,则根本不会对其进行验证。我希望它只在那里输入新密码时才能验证。在这种情况下是否可以进行条件验证?
答案 0 :(得分:2)
要在验证表单中添加一些逻辑,过程非常简单。您可以将callable传递给'validation_groups'OptionsResolverInterface。
示例(来自Symfony2书):
use Symfony\Component\Form\FormInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => function(FormInterface $form) {
$data = $form->getData();
if (Entity\Client::TYPE_PERSON == $data->getType()) {
return array('person');
} else {
return array('company');
}
},
));
}
或者:
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => array(
'Acme\AcmeBundle\Entity\Client',
'determineValidationGroups',
),
));
}
退房:http://symfony.com/doc/current/book/forms.html#groups-based-on-the-submitted-data
修改1 :
试试这个:
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => function(FormInterface $form) {
$account = $form->getData();
$password = $account->getPassword();
if (!empty($password)) {
return array('group_with_password');
} else {
return array('group_without_password');
}
},
));
}
编辑2 :
您可以使用表单事件Symfony2 [1]。事件Symfony \ Component \ Form \ FormEvents :: PRE_SUBMIT在为用户对象设置之前为您提供数组上的数据。
一种好方法是使用另一个属性(未映射到数据库)来存储用户键入的密码。像这样:
<?php
/**
* @ORM\Entity
* @ORM\Table(name="user")
*/
class User {
/**
* @var integer
*
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* The password encrypted.
* @var string
*
* @ORM\Column(type="text", nullable=true)
*/
protected $password;
/**
* Password in plain text. This field should not be mapped as Doctrine field.
*
* @var string
*/
protected $plainPasword;
}
$ plainPassword用于用户可以设置/更改密码的表单中。除非用户更改密码,否则此属性始终为null。
$ password用于存储$ plainPassword的加密版本。该属性将存储在数据库中。
要知道何时给出新密码,只需检查控制器/服务中的$ plainPassword。查看示例住所:
/**
*
* @Route("user/{id}", name="user_update")
* @Method("POST")
* @Template()
*/
public function updateAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('MyBundle:User')->find($id);
if (!$user) {
throw $this->createNotFoundException('Unable to find User entity.');
}
$editForm = $this->createEditForm($user);
$editForm->handleRequest($request);
if ($editForm->isValid()) {
$user = $editForm->getData();
$newPassword = $user->getPlainPassword();
if (!empty($newPassword)) {
$encodeFactory = $this->get('security.encoder_factory');
$passwordEncoder = $factory->getEncoder($user);
$encodedPassword = $encoder->encodePassword($newPassword, $user->getSalt());
$user->setPassword($encodedPassword);
}
$em->persist($user);
$em->flush();
return $this->redirect($this->generateUrl('user_show', array('id' => $id)));
}
return array(
'entity' => $user,
'edit_form' => $editForm->createView(),
);
}
为了简短和说教,我将所有逻辑都放在控制器中,但最好将它们移到服务中。这是FOSUserBundle做的方式[2] [3]。
[1] http://symfony.com/doc/current/components/form/form_events.html
[2] https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Model/User.php
[3] https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Model/User.php