Métodos mágicos

Son funciones definidas por PHP, las cuales el programador se encarga de definir la implementación. Sin embargo, el llamado de estas funciones ocurre cuando sea necesario y no puede ser llamadas directamente. Todas inician con una doble barra horizontal (__).

Los métodos mágicos conocidos anteriormente son:

Modificación y lectura de atributos

Para acceder y modificar atributos de un objeto se puede utilizar las funciones getter y setter, comunes en lenguajes como JAVA o C++. También es posible utilizar los métodos mágicos __get() y __set()

<?php
class Alumno {
    private $cuenta;
    private $nombre;
    private $carrera;

    public function __get($atributo)
    {
        return $this->$atributo;
    }

    public function __set($atributo, $valor)
    {
        $this->$atributo = $valor;
    }
}

// Implementación del objeto
$alumno1 = new Alumno();
// No está accediendo a los atributos, los cuales son private.
// Se está accediendo mediante los métodos mágicos.
$alumno1->cuenta = '20151000001';
$alumno1->nombre = 'Ruben Gomez';
$alumno1->carrera = 'Ingenieria en Sistemas';
echo 'Un alumno se ha creado', PHP_EOL;
echo 'Cuenta: ', $alumno1->cuenta, PHP_EOL;
echo 'Nombre: ', $alumno1->nombre, PHP_EOL;
echo 'Carrera: ', $alumno1->carrera, PHP_EOL;

?>

Inyección de atributos

Uno de los efectos secundarios de utilizar estos métodos, sin una validación correspondiente, es que podemos inyectar atributos a un objeto en tiempo de ejecución, modificando la estructura inicial de dicho objeto.

<?php

$alumno2 = new Alumno();
$alumno2->nombre = 'Juan Pueblo';
$alumno2->cuenta = '20121001234';
$alumno2->carrera = 'Medicina';

// Inyección de atributo al objeto.
$alumno2->centro = 'Ciudad Universitaria';

var_dump($alumno2);

/*
object(Alumno)#1 (4) {
  ["cuenta":"Alumno":private]=> string(11) "20121001234"
  ["nombre":"Alumno":private]=> string(11) "Juan Pueblo"
  ["carrera":"Alumno":private]=> string(8) "Medicina"
  ["centro"]=> string(20) "Ciudad Universitaria"
}
*/
?>

Para evitar la inyección de atributos se puede utilizar la función de PHP property_exists(), la cual revisa si un atributo existe o no dentro de un objeto.

<?php
class Alumno {
    private $cuenta;
    private $nombre;
    private $carrera;

    public function __get($atributo)
    {
        if (property_exists($this, $atributo))
            return $this->$atributo;
    }

    public function __set($atributo, $valor)
    {
        if (property_exists($this, $atributo))
            $this->$atributo = $valor;
    }
}

// Probar nuevamente la inyección de atributos
$alumno3 = new Alumno();
$alumno3->nombre = 'Juan Pueblo';
$alumno3->cuenta = '20121001234';
$alumno3->carrera = 'Medicina';
$alumno3->centro = 'Ciudad Universitaria';

var_dump($alumno3);

/*
object(Alumno)#1 (4) {
  ["cuenta":"Alumno":private]=> string(11) "20121001234"
  ["nombre":"Alumno":private]=> string(11) "Juan Pueblo"
  ["carrera":"Alumno":private]=> string(8) "Medicina"
}
*/

?>

Ventajas y desventajas