Я пришел к решению, основанному на ответе сумеречного ответа. Он ответил на вопрос, который я задал. Это здесь для всех в будущем — в основном для себя.
Как он упомянул, выданный лгал в $this->{$key} = $val;
Я обновил __constructor
присвоить значения защищенному атрибуту $attributes
а не сам объект, который позволяет __get
а также __set
быть запущенным правильно.
Я оставил остальную часть кода нетронутым.
Я недавно начал работать над новым проектом, с которым я не знаком, так что терпите меня. У нас есть пользовательские классы, написанные для извлечения записей из MongoDB и Sql Server. Все модели Sql Server и Mongo в конечном итоге расширят Model
класс с их соответствующими MongoModel
а также MsSqlModel
классы между ними.
Пример: 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
«расшифрованный» результат и exit;
из функции расшифровки он возвращает зашифрованное значение не bool(false)
лайк openssl_decrypt
должен вернуться, если не получится. Если я переопределить ($val = 'encryptedstring';
) параметр в расшифрованном виде с прямым значением из БД и var_dump
в расшифрованном виде все работает нормально.
Теперь остальная часть страницы / сайта работает с Vendor
с использованием Encryptable
черта характера. Я все еще могу устанавливать значения, сохранять их, извлекать их и т. Д. Единственное, что вызывает зависание, — это попытка расшифровать значение, возвращающее то же значение вместо bool(false)
лайк openssl_decrypt
следует, если это не удается, и установка значения не шифрует его.
Вы сталкиваетесь с ограничением PHP — __get
а также __set
магические функции запускаются только при обращении к атрибуту, который не существует на объекте. Их никогда не вызывают для существующих атрибутов.
Ваша реализация __set
включает в себя:
$this->$key = $value;
который мог бы устанавливать атрибуты на объекте. Любой атрибут, который был создан таким образом, больше не будет вызывать __get
или же __set
методы.
Других решений пока нет …