简体   繁体   English

Laravel / Eloquent模型属性可见性

[英]Laravel / Eloquent Model Attribute Visibility

Previously ORM's i've used have mapped database columns directly to class properties which allowed you to specific property visibility, just as you normally would to restrict access to certain properties eg passwords. 以前我使用的ORM已经将数据库列直接映射到类属性,这允许您具有特定的属性可见性,就像您通常会限制对某些属性(例如密码)的访问一样。

With Eloquent i can't seem to replicate this because database columns are mapped to the internal attributes array which contain no visibility. 有了Eloquent,我似乎无法复制这个,因为数据库列被映射到不包含可见性的内部属性数组。

My desire is to restrict the scope of access to a user password to only the object ie private. 我的愿望是将访问用户密码的范围仅限于对象即私有。

Setting a class property with visibility doesn't work because this property is then outside the scope of the Eloquent model attributes and thus the property is not mapped to the column. 设置具有可见性的类属性不起作用,因为此属性超出了Eloquent模型属性的范围,因此该属性未映射到列。

Eloquent $hidden and $guarded properties do not work as these deal with mass output (toArray, toJSON) and mass assignment rather than direct assignment. Eloquent $ hidden和$ guarded属性不起作用,因为它们处理大量输出(toArray,toJSON)和质量赋值而不是直接赋值。

I have attempted to use the accessors/mutators (getters/setters) in order to achieve this with mixed results. 我试图使用accessors / mutators(getters / setters)来实现这一目标,结果不一致。

Specifying the visibility on the accessor doesn't work because the accessor method called (eg getPasswordAttribute) is called from Eloquent\\Model->getAttribute method and as such public/protected will always work and private will always fail regardless of where the attribute it accessed from. 指定访问器上的可见性不起作用,因为调用的访问器方法(例如getPasswordAttribute)是从Eloquent \\ Model-> getAttribute方法调用的,因此public / protected将始终有效,并且private将始终失败,无论它访问的属性在何处从。

What does work however is to stop the Eloquent accessor returning the attribute altogether so any request to $user->password or $user->getAttribute ('password') fails, and then having a separate method with visibility defined in order to return the attribute directly from the Eloquent attributes array only in the scope allowed eg 然而,有效的是停止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');
}

This same approach also works for mutators (setters) for anyone wanting setter method visibility. 对于任何想要setter方法可见性的人来说,这种方法也适用于mutators(setter)。

Does this seem correct or is there a better "Laravel-Approved" way of dealing with this? 这看起来是否正确或是否有更好的“Laravel-Approved”处理方式? :) :)

I'm not aware of an 'approved' way of doing this, as such, but you could always override Eloquent's __get() magic method to check for private fields? 我不知道这样做的“批准”方式,但你总是可以覆盖__get()__get()魔术方法来检查私有字段?

The debug_backtrace() check is a bit hacky; debug_backtrace()检查有点hacky; I couldn't actually get this to work as expected without, as the getPassword() method (or basically any method in that class calling $this->password ) was still using __get . 我实际上无法按预期工作,因为getPassword()方法(或该类中调用$this->password基本上任何方法)仍在使用__get This just checks that the class calling __get is the class itself, rather than another. 这只是检查调用__get的类是类本身,而不是另一个。

It shouldn't be too inefficient as the in_array check would fail for non-private properties before it does the backtrace anyway. 它不应该太低效,因为in_array检查在非私有属性失败之前无论如何都要进行回溯。 There's probably a better way of doing it, though! 不过,可能有更好的方法!

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM