Laravel / Eloquent 模型属性可见性

Posted

技术标签:

【中文标题】Laravel / Eloquent 模型属性可见性【英文标题】:Laravel / Eloquent Model Attribute Visibility 【发布时间】:2015-01-26 00:27:05 【问题描述】:

以前我使用的 ORM 已将数据库列直接映射到类属性,这允许您查看特定属性的可见性,就像您通常会限制对某些属性的访问一样,例如密码。

使用 Eloquent 我似乎无法复制这一点,因为数据库列映射到不包含可见性的内部属性数组。

我的愿望是将用户密码的访问范围限制为仅限对象,即私有。

设置具有可见性的类属性不起作用,因为该属性超出了 Eloquent 模型属性的范围,因此该属性未映射到列。

Eloquent $hidden 和 $guarded 属性不起作用,因为它们处理大量输出(toArray、toJSON)和大量分配而不是直接分配。

我尝试使用访问器/修改器(getter/setter)来实现这一点,但结果好坏参半。

指定访问器的可见性不起作用,因为调用的访问器方法(例如 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');

同样的方法也适用于任何想要 setter 方法可见性的 mutators(setter)。

这看起来是正确的还是有更好的“Laravel-Approved”方式来处理这个问题? :)

【问题讨论】:

hidden 用于将模型输出为数组/json。没有“laravel”处理它的方式,你为什么要那样做? 我很确定隐藏你仍然可以从你的控制器(我认为)执行 $user->password,这是他试图阻止的 【参考方案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;

【讨论】:

以上是关于Laravel / Eloquent 模型属性可见性的主要内容,如果未能解决你的问题,请参考以下文章

修剪 Laravel 中所有 Eloquent 模型的所有字符串属性

Laravel 5.2 pluck() 来自 Eloquent 模型集合的多个属性

如何为 Laravel / Eloquent 模型设置默认属性值?

带有 Eloquent 的 Laravel 不会在数据库中保存模型属性

获取模型中的属性 - laravel eloquent

在使用 tinker CLI 时,Laravel 如何在 Eloquent 模型上查找和显示动态属性?