2014-11-27 6 views
6

Ранее используемые мной ORM сопоставляли столбцы базы данных непосредственно с свойствами класса, что позволяло вам определять видимость определенного объекта, как обычно, чтобы ограничить доступ к определенным свойствам, например. пароли.Видимость атрибута модели Laravel/Eloquent

С Eloquent я не могу воспроизвести это, потому что столбцы базы данных отображаются в массив внутренних атрибутов, которые не содержат видимости.

Мое желание ограничить область доступа к пользовательскому паролю только объекту i.e. private.

Установка свойства класса с видимостью не работает, потому что это свойство выходит за пределы атрибутов модели Eloquent и, следовательно, свойство не отображается в столбец.

Злоумышленные $ скрытые и $ охраняемые свойства не работают, поскольку они имеют дело с массовым выходом (toArray, toJSON) и массовым назначением, а не прямым назначением.

Я попытался использовать аксессоры/мутаторы (геттеры/сеттеры), чтобы добиться этого со смешанными результатами.

Задание видимости на аксессоре не работает, потому что метод доступа, называемый (например, getPasswordAttribute), вызывается из метода Eloquent \ Model-> getAttribute, и поскольку такой public/protected всегда будет работать, а private всегда будет терпеть неудачу, независимо от того, где к которому он обратился.

Но все же работает, чтобы остановить доступ к атрибуту 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» с этим? :)

+2

'hidden' работает для вывода модели в виде массива/json. Нет никакого способа «laravel» справиться с этим, и почему вы этого хотите? –

+0

Я уверен, что со скрытым вы все равно можете сделать $ user-> пароль от своего контроллера (я думаю), и это то, что он пытается предотвратить –

ответ

2

Я не знаю о «одобренном» способе делать это как таковое, но вы всегда можете переопределить магический метод Eloquent для проверки частных полей?

Проверка debug_backtrace() немного взломана; Я не мог заставить работу работать так, как ожидалось, так как метод getPassword() (или вообще любой метод в этом классе, вызывающий) все еще использовал __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; 
}