20

我的后端有一个简单的用户管理器,我希望能够在不设置新密码/每次都重复旧密码的情况下编辑用户。

现在,如果我在编辑用户时将密码字段留空,symfony2 会抱怨必须输入密码,当然我在注册新用户时想要这个功能,但是当我编辑它们时,我想要表单如果未填写密码框,请忽略它们。

这是如何实现的?

4

8 回答 8

27

为了其他人的参考,我以这种方式解决了这个问题。

我的表单类型:

public function buildForm(FormBuilder $builder, array $options)
{   

    $builder
        ->add('username', 'text', array('label' => 'Servernamn '))            
        ->add('plainPassword', 'repeated', array('type' => 'password', 'first_name' => 'Lösenord för server ', 'second_name' => 'Upprepa lösenord för server',));

    $builder-> addValidator(new CallbackValidator(function(FormInterface $form){
      $username = $form->get('username')->getData();
        if (empty($username)) {
          $form['username']->addError(new FormError("Du måste ange ett namn för servern"));
        }
    }));

}

我的更新操作:

public function updateServerAction($id)
{
    $em = $this->getDoctrine()->getEntityManager();

    $entity = $em->getRepository('BizTVUserBundle:User')->find($id);

    if (!$entity) {
        throw $this->createNotFoundException('Unable to find Container entity.');
    }

    $originalPassword = $entity->getPassword(); 

    $editForm   = $this->createForm(new editServerType(), $entity);

    $request = $this->getRequest();

    $editForm->bindRequest($request);

    if ($editForm->isValid()) {

        $plainPassword = $editForm->get('plainPassword')->getData();
        if (!empty($plainPassword))  {  
            //encode the password   
            $encoder = $this->container->get('security.encoder_factory')->getEncoder($entity); //get encoder for hashing pwd later
            $tempPassword = $encoder->encodePassword($entity->getPassword(), $entity->getSalt()); 
            $entity->setPassword($tempPassword);                
        }
        else {
            $entity->setPassword($originalPassword);
        }

        $em->persist($entity);
        $em->flush();

        return $this->redirect($this->generateUrl('Server'));
    }

因此,如果设置了我的用户密码,则更新我的用户密码,否则保留原始密码。

于 2012-08-17T21:08:01.507 回答
16

在您的密码属性的实体设置器上,使其如下所示:

/**
 * Set password
 *
 * @param string $password
 * @return User
 */
public function setPassword($password)
{
    if (!is_null($password)) {
        $this->password = $password;
    }

    return $this;
}

诀窍是检查传递的参数是否为空,如果不是则仅设置。

于 2014-08-29T14:59:36.950 回答
4

如果您需要将所需选项添加到 $options 数组。例子:

public function buildForm(FormBuilder $builder, array $options)
{   

    $builder
        ->add('username', 'text', array('label' => 'Servernamn '))            
        ->add('plainPassword', 'repeated', array(
                  'type' => 'password', 
                  'first_name' => 'password', 
                  'second_name' => 'repeat_password', 
                  'required' => false,
            ));
}
于 2012-12-20T14:45:04.880 回答
2

我所做的是保持UserType原样,只删除控制器中的密码字段:

/**
 * @Route("/users/edit/{username}", name="user_edit")
 */
public function editAction(Request $request, User $user)
{
    $form = $this->createForm(UserType::class, $user);

    // Remove the password field when editing the user
    // Otherwise it must be entered each time the user is edited
    // We can change the password via a special edit-user-password page
    $form->remove('password');

    $form->handleRequest($request);

    if ($form->isValid()) {
        // ...
    }
}

这样你就可以有一个单一的 UserType,在 editAction 和 newAction 中可以重用。

请务必在 .$form->remove('password');之前添加该行$form->handleRequest($request);

于 2016-07-15T11:12:24.313 回答
0

有一篇文章提供了许多选项来满足您的要求,来自 Symfony2 食谱,特别是以下部分对我有用:

根据基础数据自定义表单

下面是实现:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    // ...
    $builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) {
        $product = $event->getData();
        $form = $event->getForm();

        // check if the Product object is "new"
        // If no data is passed to the form, the data is "null".
        // This should be considered a new "Product"
        if (!$product || null === $product->getId()) {
            $form->add('name', 'text');
        }
    });
}
于 2014-03-23T08:30:21.783 回答
0

Symfony 5 方法:

在控制器类中:

/**
 * @Route("/user/{id}/edit")
 */
public function updateUser(
    $id, // See 'Route' annot., needed to `find()` User, adjust to your needs
    User $user,
    Request $request,
    UserPasswordEncoderInterface $passwordEncoder,
    UserRepository $userRepository
): Response {
    $form = $this->createForm(UserFormType::class, $user);

    // if password field is required by default, we have to `add()` it again
    // with `required` set to `false`
    $form->add( 
        'plainPassword',
        PasswordType::class,
        [
            // do not use Constraint NotBlank()
            'required' => false,
            'mapped' => false
        ]
    );

    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $entity = $userRepository->find($id); // as above, adjust to your needs

        if (!$entity) {
            throw $this->createNotFoundException('User does not exist!');
        }

        $originalPassword = $entity->getPassword();

        /** @var User $user */
        $user = $form->getData();

        // keep original password if new one isn't provided
        if (!empty($form['plainPassword']->getData())) {
            $user->setPassword(
                $passwordEncoder->encodePassword(
                    $user,
                    $form['plainPassword']->getData()
                )
            );
        } else {
            // set old password
            $user->setPassword($originalPassword);
        }

        $em = $this->getDoctrine()->getManager();
        $em->persist($user);
        $em->flush();

        return new Response('User updated!');
    }

    return $this->render(
        'admin/user_edit.html.twig',
        [
            'requestForm' => $form->createView(),
        ]
    );
}
于 2020-09-08T22:06:46.963 回答
-1

对于验证,使用 2 个不同的验证组并通过可调用函数设置正确的一个。

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add(
        'oldPassword',
        PasswordType::class,
        [
            'constraints' => new UserPassword([
                'groups' => 'profile_password',
            ]),
            'mapped' => false,
            'required' => false,
        ]
    );

    $builder->add(
        'plainPassword',
        PasswordType::class,
        [
            'constraints' => new NotBlank([
                'groups' => 'profile_password',
            ]),
            'mapped' => false,
            'required' => false,
        ]
    );
}

/**
 * {@inheritdoc}
 */
public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(
        [
            'validation_groups' => function (FormInterface $form) {
                $newPassword = $form->get('plainPassword')->getData();
                $oldPassword = $form->get('oldPassword')->getData();
                if ($oldPassword || $newPassword) {
                    return ['profile', 'profile_password'];
                } else {
                    return ['profile'];
                }
            },
        ]
    );
}
于 2016-09-05T09:23:27.717 回答
-4

你可以用

if (empty($password)) {
     //edit the password
}

尝试将其修复到表单的 PHP 中。

于 2012-08-14T21:57:27.713 回答