我已经找到了基于duskwuff的答案的解决方案。他确实回答了我问的问题。这是为了未来的任何人 - 主要是我自己。
正如他在$this->{$key} = $val;
我已更新__constructor
以将值分配给受保护的属性$attributes
,而不是允许__get
和__set
正确触发的对象本身。
我已将其余代码保持不变。
我最近开始研究一个我不熟悉的新项目,所以请耐心等待。我们编写了自定义类来从MongoDB和Sql Server中获取记录。所有Sql Server和Mongo模型最终将扩展Model
类,其中包含各自的MongoModel
和MsSqlModel
类。
Ex:Vendor extends MongoModel
> MongoModel extends DatabaseModel
> DatabaseModel extends Model
class Model implements JsonSerializable, IteratorAggregate {
...
public function __construct($attributes = []) {
foreach ( $attributes as $key => $val )
$this->{$key} = $val;
}
...
public function &__get($key) {
if ( $this->isPrivateKey($key) ) {
return $this->$key;
} else {
return $this->attributes[$key];
}
}
public function __set($key, $value) {
if ( $this->isPrivateKey($key) ) {
$this->$key = $value;
} else {
$this->attributes[$key] = $value;
}
}
...
}
出于测试目的,我在Cryptarch
模型文件中包含了Encryptable
类和Vendor
类。 Cryptarch
只有两个函数encrypt
和decrypt
- 如果需要,我可以发布它们,但它们并不特别,因为我不是安全专家。
trait Encryptable {
public function &__get($key) {
$value = parent::__get($key);
if ( in_array($key, $this->encryptable) ) {
return Cryptarch::decrypt($value);
}
return $value;
}
public function __set($key, $value) {
if ( in_array($key, $this->encryptable) ) {
$value = Cryptarch::encrypt($value);
}
parent::__set($key, $value);
}
}
class Vendor extends MongoModel
{
use Encryptable;
protected $encryptable = [
'ssn'
];
...
}
有了这个,我试图在设置(加密)或获取(解密)模型的属性时自动加密/解密敏感信息。
在我的页面上,我只是加载我要测试的记录:
$res = Vendor::load('myid');
如果我var_dump($res->ssn)
,我会获得加密值,而不是解密值。
如果我设置值$res->ssn = 'somethingelse';
和var_dump($res->ssn)
,则输出string(13) "somethingelse"
。
但是,如果我从__set
删除Encryptable
功能并尝试输出$res->ssn
,我会获得正确解密的值。
如果我var_dump
Cryptarch::decrypt($val)
中的参数我从数据库中获取了正确的值(已加密) - 但如果我尝试var_dump
解密了'来自decrypt函数的结果和exit;
返回加密值bool(false)
,而openssl_decrypt
如果失败则应返回$val = 'encryptedstring';
。如果我用DB中的直接值覆盖(var_dump
)解密用的参数,并且Vendor
解密后的结果可以正常工作。
现在,页面/网站的其余部分使用Encryptable
特征与bool(false)
一起使用。我仍然可以设置值并保存它们并获取它们等。导致挂起的唯一原因是尝试解密该值返回相同的值而不是像openssl_decrypt
那样cl1=np.count_nonzero(im == 1) #1=class 1,
cl2=np.count_nonzero(im == 2) #2=class 2,
cl0=65536-(cl1+cl2)
sum_=cl0+cl1+cl2
median_=np.median([cl0,cl1,cl2])
print cl0,cl1,cl2
print median_
try:
w0=round(median_/(cl0/sum_),4) # EAFP
except ZeroDivisionError:
w0=0
try:
w1=round(median_/(cl1/sum_),4) # EAFP
except ZeroDivisionError:
w1=0
try:
w2=round(median_/(cl2/sum_),4) # EAFP
except ZeroDivisionError:
w2=0
W=[w0,w1,w2]
print W
如果失败了,并设置值不会加密它。
答案 0 :(得分:2)
您正在遇到PHP的限制 - __get
和__set
魔术函数仅在访问对象上不存在的属性时触发。永远不会要求它们存在属性。
您对__set
的实施包括:
$this->$key = $value;
可以设置对象的属性。以这种方式创建的任何属性都将不再调用__get
或__set
方法。