Hid*_*dde 9 php types doctrine-orm
我使用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);
}
}
Run Code Online (Sandbox Code Playgroud)
我删除了所有不需要的代码.
经过几个小时的深入研究 Doctrine 代码后,我找到了自己问题的答案。
下面显示了我的解决方案的概要以帮助其他人。
首先,我创建了一个简单的值类,它可以保存任何类型的 PHP 值。它有一个__toString()方法可以将其转换回原始值。
代码:
class Value {
private $value;
public function __construct($value) {
$this -> value = $value;
}
public function __toString() {
return $this -> value;
}
}
Run Code Online (Sandbox Code Playgroud)
班级EncryptedType保持完全相同。重点是实体的价值。当必须在数据库中强制更新类的属性(从而使用该类EncryptedType)时,它将按以下方式设置:
foreach (self::$properties as $property) {
$value = $accessor -> getValue($entity, $property);
if ($value !== null) {
$accessor -> setValue($entity, $property, new Value($value));
}
}
Run Code Online (Sandbox Code Playgroud)
($accessor是一个属性访问器。)
注意new Value(...)包装器,它将确保 Doctrine 注意到属性值的变化并在数据库中进行更改。当然,该值将从__toString()方法中获取,这正是我们所需要的。