Los nombres de los métodos __construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone() y __debugInfo() son mágicos en las clases PHP. No se puede tener métodos con estos nombres en ninguna clase a menos que se desee la funcionalidad mágica asociada a estos.
PHP se reserva todos los nombres de los métodos que comienzan con __ como mágicos. Se recomienda que no utilice los nombres de métodos con __ en PHP a menos que desee alguna funcionalidad mágica documentada.
serialize() comprueba si la clase tiene un método con
el nombre mágico __sleep(). Si es así,
el método se ejecuta antes de cualquier serialización. Se puede limpiar el objeto y se supone
que devuelve un array con los nombres de todas las variables de el objeto que se va a serializar.
Si el método no devuelve nada, entonces NULL
es serializado y un error E_NOTICE
es emitido.
Nota:
No es posible para __sleep() devolver nombres de propiedades privadas en las clases padres. Hacer esto resultaría un nivel de error
E_NOTICE
. En su lugar, puede utilizar la interfaz Serializable.
El uso para el que está destinado __sleep() consiste en confirmar datos pendientes o realizar tareas similares de limpieza. Además, el método es útil si tiene objetos muy grandes que no necesitan guardarse por completo.
Por el contrario, unserialize() comprueba la presencia de un método con el nombre mágico __wakeup(). Si está presente, este método puede reconstruir cualquier recurso que el objeto pueda tener.
El uso para el que está destinado __wakeup() es restablecer las conexiones de base de datos que se puedan haber perdido durante la serialización y realizar otras tareas de reinicialización.
Ejemplo #1 Sleep y wakeup
<?php
class Connection
{
protected $link;
private $dsn, $username, $password;
public function __construct($dsn, $username, $password)
{
$this->dsn = $dsn;
$this->username = $username;
$this->password = $password;
$this->connect();
}
private function connect()
{
$this->link = new PDO($this->dsn, $this->username, $this->password);
}
public function __sleep()
{
return array('dsn', 'username', 'password');
}
public function __wakeup()
{
$this->connect();
}
}?>
El método __toString() permite a una clase
decidir cómo comportarse cuando se le trata como un string. Por ejemplo,
lo que echo $obj; mostraría. Este método debe
devolver un string, si no se emitirá un nivel de error fatal E_RECOVERABLE_ERROR
.
No se puede lanzar una excepción desde dentro un método __toString(). Hacerlo resultará en un error fatal.
Ejemplo #2 Ejemplo simple
<?php
// Declarar una clase simple
class TestClass
{
public $foo;
public function __construct($foo)
{
$this->foo = $foo;
}
public function __toString()
{
return $this->foo;
}
}
$class = new TestClass('Hola Mundo');
echo $class;
?>
El resultado del ejemplo sería:
Hola Mundo
Antes de PHP 5.2.0 el método
__toString()
se llama sólo cuando se combina directamente con
echo o print.
Desde PHP 5.2.0, se le llama en cualquier contexto de string (e.j. en
printf() con el modificador %s) pero no
en el contexto de otros tipos (e.j. con el modificador %d).
Desde PHP 5.2.0, la conversión de los objetos sin el método __toString()
a string podría causar E_RECOVERABLE_ERROR
.
El método __invoke() es llamado cuando un script intenta llamar a un objeto como si fuera una función.
Nota:
Esta característica está disponible desde PHP 5.3.0.
Ejemplo #3 Uso de __invoke()
<?php
class CallableClass
{
public function __invoke($x)
{
var_dump($x);
}
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>
El resultado del ejemplo sería:
int(5) bool(true)
$properties
)Este método static es llamado para las clases exportadas por var_export(), desde PHP 5.1.0.
El único parámetro de este método es un array que contiene las propiedades exportadas en la forma array('property' => value, ...).
Ejemplo #4 Uso de __set_state() (desde PHP 5.1.0)
<?php
class A
{
public $var1;
public $var2;
public static function __set_state($an_array) // A partir de PHP 5.1.0
{
$obj = new A;
$obj->var1 = $an_array['var1'];
$obj->var2 = $an_array['var2'];
return $obj;
}
}
$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';
eval('$b = ' . var_export($a, true) . ';'); // $b = A::__set_state(array(
// 'var1' => 5,
// 'var2' => 'foo',
// ));
var_dump($b);
?>
El resultado del ejemplo sería:
object(A)#2 (2) { ["var1"]=> int(5) ["var2"]=> string(3) "foo" }
Nota: Al exportar un objeto, var_export() no comprueba si __set_state() está implementado por la clase del objeto, por lo que la reimportación de tales objetos fallará si __set_state() no está implementado. Esto, en particular, afecta a algunas clases internas. Es responsabilidad del programador verificar que solamente se vayan a reimportar los objetos cuya clase implemente __set_state().
Este método es invocado por var_dump() al volcar un objeto para obtener las propiedades que deberían mostrarse. Si el método no está definido sobre un objeto, se mostrarán todas las propiedades públicas protegidas y privadas.
Esta característica se añadió en PHP 5.6.0.
Ejemplo #5 Utilizar __debugInfo()
<?php
class C {
private $prop;
public function __construct($val) {
$this->prop = $val;
}
public function __debugInfo() {
return [
'propSquared' => $this->prop ** 2,
];
}
}
var_dump(new C(42));
?>
El resultado del ejemplo sería:
object(C)#1 (1) { ["propSquared"]=> int(1764) }