Symfony表单验证与验证器服务

时间:2015-09-23 15:41:33

标签: php forms validation symfony

我有一个奇怪的问题,我想我错过了什么。

我正在使用Symfony 2.7而且我正在使用用户密码更新功能。

我有一个具有多个属性的用户实体(Extends FosUserBundle用户实体)。其中一个是plainPassword(当然没有持久化到DB)。

user.php的     

...

/**
 * @ORM\Table(name="prefix_users")
 * @ORM\Entity(repositoryClass="UserRepository")
 *
 * @UniqueEntity(fields={"email"}, message="unique", groups={"registration"})
 * @UniqueEntity("username", message="unique", groups={"registration"})
 *
 * @ExclusionPolicy("all")
 */
class User extends BaseUser
{

...

    /* @var string
     *
     * @Assert\NotBlank(message="blank",groups={"accountUpdate", "passwordUpdate"})
     * @Assert\Length(min=8, minMessage="short", max=4096, maxMessage="long")
     */
    protected $plainPassword;

正如您所看到的,我使用注释来验证我的属性。我还使用验证组来确保只验证正确的属性。

我创建了一个表单

UserUpdatePasswordType.php     

class UserUpdatePasswordType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('plainPassword', 'repeated', array(
            'type' => 'password',
            'invalid_message' => 'password_mismatch',
        ));
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'My\Bundle\UserBundle\Entity\User',
            'csrf_protection' => false,
            'intention' => 'resetting',
            /**
             * Need to add method to prevent this form from bein marked as invalid.
             * @see http://sroze.io/2013/10/30/symfony2-form-patch-requests-and-handlerequest-form-never-valid/
             */
            'method' => 'PATCH'
        ));
    }

我正在使用FOSRestBundle构建一个安静的API,如果表单验证失败,我想提供一个漂亮而干净的输出。

据我所知,我可以通过两种方式验证表单:

  1. $ formErrors = $ this-> get('验证器') - > validate($ user,null,[' passwordUpdate']);
  2. $ form-> isValid()并获取错误$ form-> getErrors()
  3. 现在奇怪的部分来了,上面的两种方法给出了不同的验证错误。

    请求参数

    user_update_password[plainPassword][first]:sffsdfdsfds
    user_update_password[plainPassword][second]:fdsfdsfsd
    

    来自$ formErrors的响应= $ this-&gt; get(&#39;验证器&#39;) - &gt;验证($ user,null,[&#39; passwordUpdate&#39;]); < /强> 响应不正确,因为plainPassword不是空白​​。

    {
          "property_path": "plainPassword",
          "message": "blank"
    }
    

    回复表格$ form-&gt; isValid()似乎看起来更好

    "form": {
          "children": {
            "plainPassword": {
              "children": {
                "first": {
                  "errors": [
                    "password_mismatch"
                  ]
                },
                "second": {}
              }
            }
          }
        },
        "errors": []
    

    我能看到的唯一区别是,我没有在$ form-&gt; isValid()中提供验证组名称。

    为什么我会得到不同的结果,我该怎么做才能修复? 我可以为$ form-&gt; isValid()提供验证组名称,还是应该修复$ validator-&gt;验证代码的问题?

    我很想知道如何在其他基于Symfony2的API中管理它......

3 个答案:

答案 0 :(得分:5)

有三个不同的原因。

  1. 在按服务验证时,您可能无法将数据从request设置为model。使用$form->submit($request)作为安全代理数据设置器
  2. 您不能在表单中使用验证组(在setDefaults中执行)BTW。在您向此注释添加组或将验证组@Assert\Length添加到Default验证程序数组
  3. 之前,您的service/form将无法使用
  4. 您在表单中使用了repeated类型,与您的模型Constraints相比,它有额外的Constraints。表单验证器检查属于通过的验证组的模型和表单约束(默认情况下使用默认&#39;组)

答案 1 :(得分:2)

实际上,还有另一个区别(除了使用验证组)。 当您使用Form(而不仅仅是Validator)时,涉及'repeated'类型。

  

验证

     

重复字段的一个关键特征是内部   强制执行验证(你不需要做任何事情来设置它)   这两个字段具有匹配值。如果这两个字段没有   匹配,将向用户显示错误。

所以实际上在一种情况下你正在使用一个额外的约束,而在另一种情况下你不是。没有惊喜验证会给出不同的结果。

所以在你的情况下,我可能会在User对象中为密码自己实现“repeat”,并使用验证器服务。

我看到的另一个选项是使用Form对象来验证User,但它不是一个干净清晰的API制作方法。

答案 2 :(得分:-2)

最大的区别是一个验证器正在验证模型,另一个验证表单数据。该模型要求该字段不为空。 FOSUser bundle ChangePasswordFormTypeUserPassword constraint添加到表单以进行验证。 UserPassword验证程序检查表单值是否已正确提交。

如果您在API中使用www-form-urlencoded数据,请使用表单验证程序。它将提供更精确的错误,因为它们与提交的数据状态有关,而不是数据转换为模型后的状态。