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

Symfony data transformer after $form->isValid()

我 运行 很难理解 SymfonyDataTransformers 中的数据是如何处理的。

我只有一个密码表单。只有一个领域。此字段属于必须在 .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());

以及 t运行sformer 本身:

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 但我希望有一种更优雅的方式。

我错了吗?

根据 documents

你不能

Symfony's form library uses the validator service internally to validate the underlying object after values have been submitted.

所以你实际上不是在验证表单,而是验证其下的对象没有 "notion" 的普通密码。
一个不太优雅的解决方案是在您的用户中包含一个简单的密码字段并且不保留它。然而,您可能无法验证您现有的用户对象(例如:在更新表单中),因为它们的普通密码字段将是 null。要解决这个问题,您可以创建一个自定义验证器,仅当用户不是 new 时才检查 $plainPassword 字段的有效性。您可以通过使用学说的 UnitOfWork 或检查用户的 id 是否为 null.
来检查 我建议您也看看 FOSUserBundle 它有(或曾经有)与普通密码字段类似的方法并且 可能 有您要找的东西。