php - accessors - Laravel/Eloquent Attribute Attribute Visibility
php laravel collection (1)
No conozco una forma "aprobada" de hacer esto, como tal, pero siempre se puede anular el método mágico de Eloquent __get()
para buscar campos privados.
La comprobación de debug_backtrace()
es un poco hacky; En realidad, no podía hacer que funcionara como esperaba, ya que el método getPassword()
(o básicamente cualquier método de esa clase que llamaba $this->password
) todavía estaba usando __get
. Esto solo comprueba que la clase que llama __get
es la clase misma, en lugar de otra.
No debería ser demasiado ineficaz, ya que la verificación in_array fallaría para las propiedades no privadas antes de que haga el backtrace de todos modos. ¡Sin embargo, es probable que haya una mejor manera de hacerlo!
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;
}
Anteriormente, los ORM que he utilizado tenían asignadas columnas de la base de datos directamente a las propiedades de la clase, lo que le permitía visibilidad específica de la propiedad, del mismo modo que normalmente restringiría el acceso a ciertas propiedades, por ejemplo, contraseñas.
Con Eloquent no puedo replicar esto porque las columnas de la base de datos están mapeadas a la matriz de atributos internos que no tienen visibilidad.
Mi deseo es restringir el alcance del acceso a la contraseña de un usuario a solo el objeto, es decir, privado.
Establecer una propiedad de clase con visibilidad no funciona porque esta propiedad está fuera del alcance de los atributos del modelo Eloquent y, por lo tanto, la propiedad no está asignada a la columna.
Las propiedades $ ocultas y ocultas no funcionan, ya que se trata de salidas masivas (para Array, toJSON) y asignación masiva en lugar de asignación directa.
Intenté usar los accessors / mutators (getters / setters) para lograr esto con resultados mixtos.
La especificación de la visibilidad en el descriptor de acceso no funciona porque el método de acceso llamado (por ejemplo, getPasswordAttribute) se llama desde el método Eloquent / Model-> getAttribute y como tal public / protected siempre funcionará y privado siempre fallará independientemente del lugar al que accedió el atributo de.
Sin embargo, lo que sí funciona es detener el acceso Eloquent devolviendo el atributo por completo, por lo que cualquier solicitud de $ usuario-> contraseña o $ usuario-> getAttribute (''contraseña'') falla, y luego tener un método separado con visibilidad definida para devolver el atributo directamente de la matriz de atributos Eloquent solo en el alcance permitido, por ejemplo
/**
* 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'');
}
Este mismo enfoque también funciona para mutadores (setters) para cualquiera que desee visibilidad del método setter.
¿Esto parece correcto o hay una mejor forma de lidiar con esto "aprobada por Laravel"? :)