Symfony2 - 使用空字段提交表单时使用实体值作为默认值

时间:2014-07-18 11:00:11

标签: php forms validation symfony

我在Symfony 2中构建了一个Web应用程序,我有一个用于保存注册用户的User实体类。

每个用户当然至少应该拥有用户名和密码,因此,我对实体中的两个字段使用@Assert\NotBlank验证规则。用户名是静态的,但是,能够更改密码是可取的。

因此,我正在构建一个表单,其中登录的用户可以更改其密码(以及其他内容)。此表单利用Symfony中的重复字段类型进行密码确认。

现在,在大多数情况下,我猜用户不希望更改密码,而是更新其个人资料中的其他字段。因此,我希望他们可以将密码字段留空。但是,这会干扰NotBlank验证规则。

删除NotBlank验证规则当然是一种选择。虽然,这几乎不是我寻找的解决方案,因为这会导致用户以空白密码结束的问题。

最后,据我所知,symfony Request对象在表单提交时将表单数据自动填充回User实体。

现在,我的问题是:有没有办法,在空密码字段下,让Symfony用数据库中的现有密码而不是空值重新填充用户实体?这将允许验证通过并且在保存时不会导致对密码的任何不期望的更改。

这是实体

中密码字段的代码
/**
 * @var string
 * 
 * @ORM\Column(name="password",type="string",length=255) 
 * @Assert\NotBlank()
 * @Assert\Type(type="string")
 * @Assert\Length(max="255")
 * @Assert\NotEqualTo(value="password")
 */
private $password;

这是用于生成表单的代码

private function initForm($user) {
  return $this->createFormBuilder($user)
           ->add('name', 'text')
           ->add('mail', 'email')
           ->add('password', 'repeated', [
              'type' => 'password',
              'invalid_message' => 'The password fields must match.',
              'first_options' => ['label' => false],
              'second_options' => ['label' => false] //set to false to hide label in view
           ])
           ->add('save', 'submit')->getForm();
}

这是/profile/edit页面的操作代码:

/**
 *  @ParamConverter("user",class="MyBundle:User")
 */
public function editAction(User $user, Request $request) {

   $form = $this->initForm($user);
   $form->handleRequest($request);

   if ($form->isValid()) {
      //update to database and redirect user back to profile_view
      $this->getDoctrine()->getManager()->flush();
      return $this->redirect($this->generateUrl('profile_view'));
   }

   return $this->render('MyBundle:User:edit.html.twig',
                        array('form' => $form->createView()));
}

提前感谢您的帮助!

修改

我确实尝试了#34;显而易见的"方法,即temporarilly将原始密码存储在变量中,并且" put"如果在提交表单后它是空白的,则返回:

/**
 * @ParamConverter("user",
                   class="MyBundle:User")
 */
public function editAction(User $user, Request $request) {
   $password = $user->getPassword();

   $form = $this->initForm($user)->getForm();
   $form->handleRequest($request);

   if ( $user->getPassword() == NULL ) {
       $user->setPassword($password);
       $form = $this->initForm($user)->getForm(); //this is the problem

   }

   if ( $form->isValid() ) {
       //update to database and redirect user back to profile view
       $this->getDoctrine()->getManager()->flush();
       return $this->redirect($this->generateUrl('profile_view'));
   }
   return $this->render('MyBundle:User:edit.html.twig',
                        array('form' => $form->createView()));
}

然而,由于明显的原因,这不起作用。当表单在if语句中重新初始化时,Symfony发现表单从未提交过,即未执行验证。添加$form->handleRequest($request)会让我们忘记第一个问题,即密码字段可能为空白。

虽然我觉得很奇怪。 Symfony验证实体而不是表单。但是删除问题行$form->initForm($user)->getForm()仍然无法正常工作,尽管该实体应该有效。

2 个答案:

答案 0 :(得分:1)

我认为这不是一个好主意。正确的方法是创建一个单独的表单来更改用户密码。示例:twitterfacebookgoogle

答案 1 :(得分:0)

解决方案是使用未存储在数据库中的额外类成员$rawPassword仅用于表单。当然,您将按照问题中的定义保留数据库存储的$password变量。

在您的修改操作中,如果您的用户定义为$form->bind($request);密码,则必须在$rawPassword之后进行测试。如果是这种情况,请使用编码值$password更新$rawPassword,然后刷新。

编辑:$form->bind($request);低于2.3,$form->handleRequest($request);否则。