Symfony2 执行表单验证,而不是数据库验证


Symfony2 do Form validation rather then database validation

我有一个信用卡实体,现在我想在实体中对此执行基本验证,例如:

/**
 * @ORM'Column(name="number", type="string", length=255)
 * @Assert'CardScheme(
 *     schemes={"VISA", "MASTERCARD", "DISCOVER", "DINERS"},
 *     message="The card number is not valid, we only support Visa, Mastercard, Discover og Diners club."
 * )
 */
private $number;

但问题是我正在加密存储卡号。

它们最终看起来完全不同,在我的表单类型中,我这样做是为了加密值并删除所有不合时宜的东西。

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('number')
        ->add('expiration_year', 'choice', array(
            'required' => true,
            'choices' => $this->buildYearChoices()
        ))
        ->add('expiration_month', 'choice', array(
            'required' => true,
            'choices' => array(
                '01' => '01',
                '02' => '02',
                '03' => '03',
                '04' => '04',
                '05' => '05',
                '06' => '06',
                '07' => '07',
                '08' => '08',
                '09' => '09',
                '10' => '10',
                '11' => '11',
                '12' => '12',
            )
        ))
        ->add('cvc', 'text');
    $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event)
    {
        $data = $event->getData();
        $number = preg_replace("/[^0-9]/", "", $data['number']);
        $data['number'] = $number;
        $event->setData($data);
    });
    $builder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event)
    {
        $credit_card = $event->getData();
        $number = $credit_card->getNumber();
        $customer_helper = $this->container->get('customer_helper');
        $crypt = $customer_helper->encryptCreditCardNumber($number);
        $credit_card->setNumber($crypt);
        $event->setData($credit_card);
    });
}

即使我知道表单验证是在pre_submit执行的,当我在提交上加密它时,我仍然会收到验证错误

编辑:加密和解密 emthods:

public function encryptCreditCardNumber($plaintext) {
    $ivSize = mcrypt_get_iv_size(self::CIPHER, self::MODE); //Gets the size of the IV belonging to a specific cipher/mode combination.
    $iv = mcrypt_create_iv($ivSize, MCRYPT_DEV_RANDOM); //Creates an initialization vector (IV) from a random source.
    $ciphertext = mcrypt_encrypt(self::CIPHER, $this->container->getParameter('cc_encryption_key'), $plaintext, self::MODE, $iv); //Encrypts the data and returns it.
    return base64_encode($iv.$ciphertext); //Encode Base 64
}
public function decryptCreditCardNumber($ciphertext) {
    $ciphertext = base64_decode($ciphertext); //Decode Base 64
    $ivSize = mcrypt_get_iv_size(self::CIPHER, self::MODE); //Gets the size of the IV belonging to a specific cipher/mode combination.
    if (strlen($ciphertext) < $ivSize) {
        throw new Exception('Missing initialization vector');
    }
    $iv = substr($ciphertext, 0, $ivSize);
    $ciphertext = substr($ciphertext, $ivSize);
    $plaintext = mcrypt_decrypt(self::CIPHER, $this->container->getParameter('cc_encryption_key'), $ciphertext, self::MODE, $iv); //Decrypts the data and returns it.
    return rtrim($plaintext, "'0");
}

您可以prePersist捕获教义事件,并preUpdate动态将纯代码替换为加密代码(就在持久化数据之前,在表单验证之后)。

要解密它,您可以使用 postLoad .

更多关于教义事件的信息在这里。

请注意,教义事件与形式事件不同,不会干扰形式或验证(甚至可能根本没有形式)。

编辑:注入密钥

每当需要将静态信息注入实体(如参数或函数)时,请使用依赖项注入。

如果您有捆绑包,请转到DependencyInjection文件夹并编辑Configuration.php文件(还是另一个文件?我现在不记得了)。

您要查找的是使用 load 方法加载参数的方法。

之后,从配置中获取所需的参数,并将其设置为类的静态成员,如下所示:

MyEntity::$secretKey = $configuration->getParameter('secretkey');

在实体内部,只需仔细阅读以下信息:

self::$secretKey

我把这个写出来,所以很多不准确的地方可能已经溜进去了。必要时更正。关键是静态注入参数,如上所示。

您可以创建非映射实体属性以进行验证:

/**
 * @Assert'CardScheme(
 *     schemes={"VISA", "MASTERCARD", "DISCOVER", "DINERS"},
 *     message="The card number is not valid, we only support Visa, Mastercard, Discover og Diners club."
 * )
 */
private $rawNumber;
/**
 * @ORM'Column(name="number", type="string", length=255)
 */
private $number;

然后在表单验证后使用rawNumber的加密值设置数字:

$creditCard->setNumber(
    your_encryption_function(
        $creditCard->getRawNumber()
    )
);