【问题标题】:Update database values with same PHP values using Doctrine type使用 Doctrine 类型更新具有相同 PHP 值的数据库值
【发布时间】:2015-12-28 11:05:45
【问题描述】:

我正在使用 Doctrine2 类型来加密数据库值。该类型通过加密和解密将 PHP 值在内部与数据库值相互转换。由于 Doctrine2 类型,这非常有效。

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


我的愿望是:

假设我有一个实体。我想强制使用 Doctrine 对实体的所有属性进行加密或解密。为此,我强制类型内的数据库值以加密或解密形式存储。

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

如何做到这一点?


Doctrine 类型的一些代码:

<?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);
    }
}

我已删除所有不需要的代码。

【问题讨论】:

    标签: php types doctrine-orm


    【解决方案1】:

    这不是bug吗?

    解决方法:如果实体由经理管理,那么它有一个状态STATE_MANAGED,当你将它更改为STATE_NEW并强制更新时,这可以解决你的问题。

    【讨论】:

    • 我不这么认为。 Doctrine 如何知道 EncryptedType 类中某些静态字段的变化。恐怕这必须通过使用 Doctrine 事件来解决。
    【解决方案2】:

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

    下面我的解决方案大纲显示以帮助其他人。


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

    代码:

    class Value {
        private $value;
    
        public function __construct($value) {
            $this -> value = $value;
        }
    
        public function __toString() {
            return $this -> value;
        }
    }
    

    EncryptedType 类保持不变。点是实体的价值。当一个类的属性必须在数据库中强制更新时(从而使用EncryptedType 类),它将按以下方式设置:

    foreach (self::$properties as $property) {
        $value = $accessor -> getValue($entity, $property);
        if ($value !== null) {
            $accessor -> setValue($entity, $property, new Value($value));
        }
    }
    

    $accessor 是一个属性访问器。)

    注意new Value(...) 包装器,它将确保 Doctrine 注意到属性值的更改并在数据库中进行更改。当然值会取自__toString()方法,这正是我们所需要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-22
      • 1970-01-01
      • 2012-02-11
      • 2013-03-18
      相关资源
      最近更新 更多