Un método mágico es un método al que se llama automáticamente cuando se produce un acontecimiento.
Por ejemplo __construct es un método mágico. Se ejecuta automáticamente cuando instancia la clase que contiene __construct.
Los métodos mágicos __get y __set permiten leer o modificar los atributos que no existen y en los que el acceso está prohibido.
Retome el ejemplo al inicio del capítulo con la clase Animal:
Esta vez, el atributo color es privado y el atributo peso es público:
<?php class Animal { // Declaración de atributos private $color = "gris"; public $peso = 10; public function __construct($color, $peso) // Constructor //que solicita 2 argumentos. { echo ’Llamada al constructor.<br />’; $this->color = $color; // Inicialización del color. $this->peso = $peso; // Inicialización del peso. } //métodos públicos public function comer () { } public function moverse () { } } ?>
Cuando crea una instancia de la clase Animal, puede acceder al atributo peso porque es público, pero no al atributo color porque es privado.
La página uso.php es:
<?php //carga de clases include(’Animal.class.php’); //instanciar la clase Animal $perro = new Animal("gris",8); $perro->color = "negro"; echo $perro->color."<br />"; ?>
Muestra un error porque intenta acceder directamente al atributo color, que es privado:
Llamada al constructor.
Fatal error: Cannot access private property Animal::$color in C:\Program Files\EasyPHP-DevServer-13.1VC11\data\localweb\Objeto\ uso.php on line 9
Ahora añada los métodos mágicos __get y __set en la clase Animal:
<?php class Animal { // Declaración de atributos private $color = "gris"; public $peso = 10; private $tab_atributos = array(); public function __construct($color, $peso) // Constructor //que solicita 2 argumentos. { echo ’Llamada al constructor.<br />’; $this->color = $color; // Inicialización del color. $this->peso = $peso; // Inicialización del peso. } //métodos mágicos public function __get($nombre) { echo "__get <br />"; if (isset ($this->tab_atributos[$nombre])) return $this->tab_atributos[$nombre]; } public function __set($nombre, $valor) { echo "__set <br />"; $this->tab_atributos[$nombre] = $valor; } public function __isset($nombre) { return isset ($this->tab_atributos[$nombre]); } //métodos públicos public function comer () { ... } public function moverse () { ... } } ?>
Estos métodos se activan automáticamente si el atributo es privado o no existe. Almacenan el valor en la tabla $tab_atributos, y en el índice, el nombre del atributo. El método __isset($atributo) permite saber si existe el atributo.
La página uso.php:
<?php //carga de clases include(’Animal.class.php’); //instanciar la clase Animal $perro = new Animal("gris",8); if (isset($perro->color)) { echo "El atributo color existe.<br />"; } else { echo "El atributo color no existe.<br />"; } $perro->color = "negro"; echo $perro->color."<br />"; if (isset($perro->peso)) { echo "El atributo peso existe.<br />"; } else { echo "El atributo peso no existe.<br />"; } $perro->peso = 25; echo $perro->peso."<br />"; ?>
Da como resultado:
Llamada al constructor.
El atributo color no existe.
__set
__get
Negro
El atributo peso existe.
25
Explicación:
$perro = new Animal("gris",8); da como resultado: Llamada al constructor.
isset($perro->color); devuelve falso, ya que no se puede acceder al atributo color, que es privado; por lo tanto, muestra: El atributo color no existe.
$perro->color = "negro"; da como resultado: __set. El atributo color es privado; por lo tanto, no se puede acceder a él y llama automáticamente a __set y el valor se almacena en la tabla $tab_atributos.
echo $perro->color."<br />"; da como resultado: __get y negro. El atributo color siempre es privado; por lo tanto, llama automáticamente a __get para mostrar el color.
isset($perro->peso); devuelve verdadero porque el atributo peso es público, se puede acceder a él y por lo tanto muestra: el atributo peso existe.
$perro->peso = 25; no muestra nada porque no llama a la función __set. El atributo peso es público, puede acceder directamente a él.
echo $perro->peso."<br />"; da como resultado 25. El atributo peso es público y por lo tanto puede acceder directamente a él.
Para eliminar un atributo que el método mágico __set ha añadido, debe ejecutar el método mágico __unset($atributo), que eliminará el atributo de la tabla $tab_atributos.
Añada este método en la clase Animal:
public function __unset($nombre) { if (isset($this->tab_atributos[$nombre])) unset($this->tab_atributos[$nombre]); }
Para terminar, los métodos mágicos __call y __callStatic permiten llamar a los métodos privados o que no existen. La función method_exist() comprueba si un método existe en
un objeto. Toma como argumento el objeto y el nombre del método. Devuelve true si el método existe y false si no.
La clase Animal con un método público comer() y un método privado moverse() se convierte en:
<?php class Animal { // Declaración de atributos private $color = "gris"; public $peso = 10; private $tab_atributos = array(); public function __construct($color, $peso) // Constructor //que solicita 2 argumentos. { echo ’Llamada al constructor.<br />’; $this->color = $color; // Inicialización del color. $this->peso = $peso; // Inicialización del peso. } //métodos mágicos public function __get($nombre) { echo "__get <br />"; if (isset ($this->tab_atributos[$nombre])) return $this->tab_atributos[$nombre]; } public function __set($nombre, $valor) { echo "__set <br />"; $this->tab_atributos[$nombre] = $valor; } public function __isset($nombre) { return isset ($this->tab_atributos[$nombre]); } public function __call($nombre, $argumentos) { echo "El método ".$nombre." no es accesible. Sus argumentos eran los siguientes :".implode($argumentos, ’, ’)."<br />"; if(method_exists($this, $nombre)) { $this->$nombre(implode($argumentos, ’, ’)); } } public static function __callStatic($nombre, $argumentos) { echo "El método estático ".$nombre." no es accesible. Sus argumentos eran los siguientes :".implode($argumentos, ’, ’) ."<br />"; if(method_exists(__CLASS__, $nombre)) { echo __CLASS__.’::’.$nombre.’<br />’; self::$nombre(implode($argumentos, ’, ’)); } } //método público public function comer() { echo "Método público comer() <br />"; } //método privado private function moverse($lugar) { echo "Método privado moverse() <br />"; } } ?>
La página uso.php:
<?php //carga de clases include(’Animal.class.php’); //instanciar la clase Animal $perro = new Animal("gris",8); $perro->comer(); $perro->moverse("París"); ?>
Da como resultado:
Llamada al constructor.
Método público comer()
El método moverse no es accesible. Sus argumentos eran los siguientes:París
Método privado moverse()
El código $perro->comer(); llama al método público comer(). Pero al método moverse($lugar), que es privado, no se puede acceder directamente. Llama al método mágico __call, comprueba que existe el método moverse($lugar)y llama al método moverse ($lugar).
Si el método moverse ($lugar) es estático, la llamada a la página uso.php es:
Animal::moverse("París");
Entonces llama al método mágico __callStatic.
Hay otros métodos mágicos que no se explican en este libro. Puede obtener más información sobre estos métodos en el manual de PHP, en la siguiente dirección: http://php.net/manual/es/language.oop5.magic.php
Espero haber ayudado en algo. Hasta la próxima oportunidad!
Twittear
Deberias usar algun SyntaxHighlighter para los codigos
ResponderEliminarHola JohnC, gracias por la visita y el aporte de tu comentario!
EliminarEstoy actualizando las páginas con código para agregarle referencia a un SyntaxHighlighter.
Sería bueno que me dejaran un comentario en las páginas que están sin SyntaxHighlighter.
Los mejores deseos! Hasta cualquier momento!