$form->isValid()之后的Symfony数据转换器


Symfony data transformer after $form->isValid()

我在理解Symfony的datattransformer中数据是如何处理的时候遇到了麻烦。

我有一个密码表单。只有一个领域。该字段属于User实体,必须在.yml文件中定义约束。

Software'Bundle'Entity'User:
    password:
        - NotBlank: ~
        - Length:
            min: 6
            max: 155

验证工作正常,正如预期的那样。当密码必须从字段自动编码时,问题就出现了。

    $builder->add('password', 'password', [
        'label' => 'word.password'
    ]);
    $builder->get('password')
        ->addModelTransformer(new EncodePasswordTransformer());

和变压器本身:

class EncodePasswordTransformer implements DataTransformerInterface
{
    public function transform($value)
    {
        return $value;
    }
    public function reverseTransform($value)
    {
        // encode password
        return PasswordHash::createHash($value);
    }
}

下面是结果:

表单应该包含6到155个字符,但$form->isValid()总是为真,因为PasswordHash::createHash($value)将密码编码为32个字符。我期待的是:

表单验证原始密码,如果超过6个字符然后转到$form->isValid() true,然后在验证后对密码进行编码。

我知道我可以手动编码密码,而表单是有效的,而不使用DataTransformer,但我希望有一个更优雅的方式。

我错了吗?

根据文件,你不能。

Symfony的表单库在内部使用验证器服务来在提交值之后验证底层对象。

所以你实际上不是在验证表单,而是下面的对象,它没有纯密码的"概念"。
一个不那么优雅的解决方案是在用户中包含一个纯密码字段,并且不保存。但是,您可能无法验证现有的用户对象(例如:在更新表单中),因为它们的纯密码字段将是null。为了解决这个问题,您可以创建一个自定义验证器,仅在用户不是new时才检查$plainPassword字段的有效性。你可以通过使用doctrine的UnitOfWork或者检查用户的id是否为null来检查。
我建议你也看看FOSUserBundle,它有(或曾经)一个类似的方法,以纯密码字段和可能有你正在寻找的。