Имената на функциите __construct, __destruct, __call, __callStatic, __get, __set, __isset, __unset, __sleep, __wakeup, __toString, __invoke, __set_state и __clone са вълшебни в класовете на PHP. Не може да създавате функции с тези имена във вашите класове, освен ако не ги използвате по вълшебното им предназначение.
PHP запазва всички имена на функции, започващи с __, като вълшебни. Препоръчително е да не използвате имена на функции, които започват с __ в PHP, освен ако не използвате някоя документирана вълшебна функционалност.
serialize() проверява дали в класа ви има функция с вълшебното име __sleep. Ако открие такава, то тази функция се изпълнява преди всяка сериализация. Тя би могла да изчисти обекта и се очаква да върне масив с имената на всички променливи от този обект, които ще бъдат сериалзирани. Ако методът не върне нищо, тогава се сериализира стойността NULL и се генерира грешка от тип E_NOTICE.
Предназначението на __sleep е да затвори всички връзки към бази от данни, които обектът може да има, да съхрани незаписаните данни или да изпълни други подобни изчистващи задачи. Също така функцията може да се използва и в случай, че имате много големи обекти, които няма нужда да бъдат съхранени изцяло.
Обратно - unserialize() проверява за наличието на функция с вълшебното име __wakeup. Ако тя съществува, функцията може да възстанови всички ресурси, които даден обект може да има.
Употребата на __wakeup има за цел да възстанови всички връзки към бази от данни, които може да са били прекъснати по време на сериализацията и за извършване на други повторно-инициализиращи задачи.
Example #1 Заспиване (sleep) и събуждане (wakeup)
<?php
class Connection {
protected $link;
private $server, $username, $password, $db;
public function __construct($server, $username, $password, $db)
{
$this->server = $server;
$this->username = $username;
$this->password = $password;
$this->db = $db;
$this->connect();
}
private function connect()
{
$this->link = mysql_connect($this->server, $this->username, $this->password);
mysql_select_db($this->db, $this->link);
}
public function __sleep()
{
return array('server', 'username', 'password', 'db');
}
public function __wakeup()
{
$this->connect();
}
}
?>
Методът __toString позволява на даден клас да реши как ще реагира, в случай че бъде преобразуван до низ.
Example #2 Прост пример
<?php
// Дефиниция на клас
class TestClass
{
public $foo;
public function __construct($foo) {
$this->foo = $foo;
}
public function __toString() {
return $this->foo;
}
}
$class = new TestClass('Здравей');
echo $class;
?>
Примерът по-горе ще изведе:
Здравей
Трябва да се отбележи, че до PHP 5.2.0 методът __toString ще бъде извикан, само когато е директно комбиниран с echo() или print(). От PHP 5.2.0 се извиква в контекста на всеки низов тип (например при printf() с модификатора %s), но не и в контекста на други типове (например при модификатора %d). От PHP 5.2.0 при преобразуването на обекти в низ без метода __toString ще се генерира E_RECOVERABLE_ERROR
Методът __invoke се извиква, когато даден скрипт направи опит да извика обект, както се извиква функция. The __invoke method is called when a script tries to call an object as a function.
Забележка: Тази възможност е достъпна от PHP 5.3.0.
Example #3 Употреба на __invoke
<?php
class CallableClass {
function __invoke($x) {
var_dump($x);
}
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>
Примерът по-горе ще изведе:
int(5) bool(true)
Този статичен метод се извиква за класове, експортирани от функцията var_export() от PHP 5.1.0.
Единственият параметър на метода е масив, съдържащ експортирани свойства във вида array('property' => value, ...).
Example #4 Употреба на __set_state (от PHP 5.1.0)
<?php
class A
{
public $var1;
public $var2;
public static function __set_state($an_array) // As of 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);
?>
Примерът по-горе ще изведе:
object(A)#2 (2) { ["var1"]=> int(5) ["var2"]=> string(3) "foo" }