Symfony 2 仅在字段值存在时验证 [英] Symfony 2 validate only if field value present

查看:29
本文介绍了Symfony 2 仅在字段值存在时验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Symfony2 中遇到验证系统问题.我有一个在注册和帐户更新时验证的帐户实体.该实体具有用户名、密码、姓名、电子邮件等.在帐户更新屏幕上,我允许更新帐户的用户名和密码.我希望只有在输入值时才更新帐户的密码,这可以很好地实现,但验证失败,因为验证器需要密码.如果我使用密码和没有密码的帐户创建单独的组进行注册,则根本不会对其进行验证.我希望它仅在输入新密码时进行验证.在这种情况下是否可以进行条件验证?

I am having a problem with the validation system in Symfony2. I have a Account entity which is validated on registration and account update. The entity has username, password, name, email etc. On the Account Update screen I allow to update on both the username and password for the account. I would like the password to be updated on the account only if a value is entered, which is implemented fine but the validation fails because the Validator expects a password there. If I make a separate group for registration with the password and account without the password it will not validate it at all. I want it to validate only if a new password is entered there. Is a conditional validation possible in this scenario?

推荐答案

将一些逻辑添加到您的验证表单过程中非常容易.您可以将可调用对象传递给 'validation_groups' OptionsResolverInterface.

To add some logic into your validation form process is very easy. You can pass an callable to 'validation_groups' OptionsResolverInterface.

示例(来自 Symfony2 书籍):

Example (from Symfony2 book):

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 在设置用户对象之前为您提供数组上的数据.

You could use the form events Symfony2[1]. The event Symfony\Component\Form\FormEvents::PRE_SUBMIT give you the data on an array before being set on the user object.

一个好的方法是使用另一个属性(未映射到数据库)来存储用户输入的密码.像这样:

A good approach is use another attribute (not mapped to database), to store the password typed by the user. Like this:

<?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 用于用户可以设置/更改其密码的表单.此属性始终为空,除非用户更改密码.

The $plainPassword is used in forms that user can set/change their password. This attribute always will be null, except when the users change their passwords.

$password 用于存储 $plainPassword 的加密版本.此属性将存储在数据库中.

The $password is used to store the encrypted version of $plainPassword. This attribute will be stored in database.

要知道何时给出新密码,只需检查控制器/服务中的 $plainPassword.查看示例住所:

To know when a new password is given, simply check $plainPassword in your controller/service. Check out the example abode:

/**
 *
 * @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 do[2][3]的方式.

To be short and didactic, I put all the logic in controller, but is better move them to a service. This is the way of FOSUserBundle do[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

这篇关于Symfony 2 仅在字段值存在时验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆