使用相同的PHP值更新数据库值

使用相同的PHP值更新数据库值,php,types,doctrine-orm,Php,Types,Doctrine Orm,我使用Doctrine2类型来加密数据库值。该类型通过对PHP值进行加密和解密,在内部将PHP值与数据库值进行转换。由于Doctrine2类型的原因,这一点非常有效 加密存储为base64编码字符串。每个加密字符串都有一个固定的前缀。这意味着数据库字段包含前缀识别的加密值和解密值(这是外部要求所必需的) 我的愿望如下: 假设我有一个实体。我想使用条令强制加密或解密实体的所有属性。我通过强制将类型中的数据库值以加密或解密的形式存储来实现这一点 但是,当我调用方法EntityManager::co

我使用Doctrine2类型来加密数据库值。该类型通过对PHP值进行加密和解密,在内部将PHP值与数据库值进行转换。由于Doctrine2类型的原因,这一点非常有效

加密存储为base64编码字符串。每个加密字符串都有一个固定的前缀。这意味着数据库字段包含前缀识别的加密值和解密值(这是外部要求所必需的)


我的愿望如下:

假设我有一个实体。我想使用条令强制加密或解密实体的所有属性。我通过强制将类型中的数据库值以加密或解密的形式存储来实现这一点

但是,当我调用方法
EntityManager::computeChangeSets
时,实体的所有属性都没有标记为已更改。当然,实际数据(PHP值)不会改变。但是,数据库值确实(应该)发生了变化

如何做到这一点


某些条令类型的代码:

<?php

use Doctrine\DBAL\Types\Type;

class EncryptedType extends Type {

    private static $forceDecrypt = false;

    // Encryption stuff, like encrypt () and decrypt ()

    public function convertToPHPValue($value, AbstractPlatform $platform) {
        if ($value === null) {
            return null;
        }
        return $this -> decrypt($value, false);
    }

    public function convertToDatabaseValue($value, AbstractPlatform $platform) {
        if ($value === null) {
            return null;
        }
        if (self::$forceDecrypt) {
            return (string) $value;
        }
        return $this -> encrypt((string) $value, false);
    }
}
这不是一个bug吗


解决方法:如果实体由管理者管理,那么它有一个状态
state\u managed
,当您将其更改为
state\u NEW
并强制更新时,这可以解决您的问题。

在深入研究条令代码数小时后,我找到了自己问题的答案

下面是我的解决方案的概要,以帮助他人


首先,我创建了一个简单的value类,它可以保存任何类型的PHP值。它有一个
\uu toString()
方法将其转换回原始值

代码:

EncryptedType
类保持完全相同。点是实体的值。当必须在数据库中强制更新类的属性时(从而使用
EncryptedType
类),将按以下方式进行设置:

foreach (self::$properties as $property) {
    $value = $accessor -> getValue($entity, $property);
    if ($value !== null) {
        $accessor -> setValue($entity, $property, new Value($value));
    }
}
$accessor
是属性访问器。)


请注意
新值(…)
包装器,它将确保条令注意到属性值的更改并在数据库中进行更改。当然,该值将取自
\uu toString()
方法,这正是我们需要的。

我不这么认为。条令如何知道类
EncryptedType
中某些静态字段的更改。我担心这必须通过使用条令事件来解决。
foreach (self::$properties as $property) {
    $value = $accessor -> getValue($entity, $property);
    if ($value !== null) {
        $accessor -> setValue($entity, $property, new Value($value));
    }
}