Видимость атрибута Laravel / Eloquent модели
Ранее в ORM, которые я использовал, столбцы базы данных отображались непосредственно в свойствах класса, что позволяло вам видеть конкретные свойства, как вы обычно ограничивали бы доступ к определенным свойствам, например, паролям.
С Eloquent я не могу воспроизвести это, потому что столбцы базы данных сопоставлены с массивом внутренних атрибутов, которые не содержат видимости.
Мое желание состоит в том, чтобы ограничить область доступа к паролю пользователя только объектом, то есть частным.
Установка свойства класса с видимостью не работает, потому что это свойство выходит за рамки атрибутов модели Eloquent и, следовательно, свойство не отображается в столбце.
Eloquent $ hidden и $guarded свойства не работают, так как они имеют дело с массовым выводом (toArray, toJSON) и массовым назначением, а не прямым назначением.
Я пытался использовать аксессоры / мутаторы (геттеры / сеттеры) для достижения этого со смешанными результатами.
Задание видимости для средства доступа не работает, потому что вызываемый метод средства доступа (например, getPasswordAttribute) вызывается из метода Eloquent\Model->getAttribute, и поэтому такой открытый / защищенный всегда будет работать, а частный всегда будет зависать независимо от того, к какому атрибуту он обращался от.
Однако работает то, что средство доступа Eloquent не может вернуть атрибут вообще, поэтому любой запрос к $user->password или $user->getAttribute ('password') завершается неудачно, а затем создается отдельный метод с видимостью, определенной для возврата Атрибут непосредственно из массива атрибутов Eloquent только в допустимой области, например
/**
* Return password string only for private scope
* @return string
*/
private function getPassword ()
{
return $this->attributes['password'];
}
/**
* Don't return password with accessor
* @param string $password Password
* @return void
* @throws Exception
*/
public function getPasswordAttribute ($password)
{
throw new Exception ('Password access denied');
}
Этот же подход также работает для мутаторов (сеттеров) для тех, кто хочет видеть метод установки.
Кажется ли это правильным или есть лучший "одобренный Laravel" способ справиться с этим?:)
1 ответ
Я не знаю о "одобренном" способе сделать это, как таковой, но вы всегда можете отменить Eloquent __get()
Волшебный метод для проверки приватных полей?
debug_backtrace()
проверка немного хакерская; Я не мог заставить это работать так, как ожидалось, так как getPassword()
метод (или в основном любой метод в этом классе вызова $this->password
) все еще использовал __get
, Это просто проверяет, что класс, вызывающий __get
это сам класс, а не другой.
Это не должно быть слишком неэффективно, так как проверка in_array не будет выполнена для не приватных свойств, прежде чем она все равно выполнит обратную трассировку. Хотя, возможно, есть лучший способ сделать это!
private $private = array(
'password'
);
public function __get($key)
{
// check that the class calling __get is this class, and the key isn't 'private'
if (in_array($key, $this->private) && debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['class'] != get_class()) {
throw new \Exception('Private');
}
// anything else can return as normal
return parent::__get($key);
}
public function getPassword()
{
// calling this method elsewhere should work
return $this->password;
}