Видимость атрибута 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;
}
Другие вопросы по тегам