Магические методы — это специальные методы, которые переопределяют действие PHP по умолчанию, когда над объектом выполняются определенные действия.
Осторожность
Все имена методов, начинающиеся с __
, зарезервированы PHP. Поэтому не рекомендуется использовать такие имена методов, если только это не переопределяет поведение PHP.
Следующие имена методов считаются магическими: __construct() , __destruct() , __call( ) , __callStatic( ) , __get() , __set() , __isset() , __unset() , __sleep() , __wakeup() , __serialize( ) , __unserialize() , __toString() , __invoke() , __set_state() , __clone() и __debugInfo() .
Предупреждение
Все магические методы, за исключением __construct() , __destruct() и __clone() , должны быть объявлены как public, иначе E_WARNINGбудет сгенерировано сообщение an. До версии PHP 8.0.0 для магических методов __sleep() , __wakeup() , __serialize() , __unserialize() и __set_state() не выдавалась диагностика .
Предупреждение
Если в определении магического метода используются объявления типов, они должны быть идентичны сигнатуре, описанной в этом документе. В противном случае выдается фатальная ошибка. До версии PHP 8.0.0 никакие диагностические сообщения не выдавались. Однако __construct() и __destruct() не должны объявлять возвращаемый тип; в противном случае выдается фатальная ошибка.
__sleep() и __wakeup()
public __sleep(): array
public __wakeup(): void
serialize() проверяет, есть ли в классе функция с магическим именем __sleep() . Если это так, эта функция выполняется до любой сериализации. Он может очищать объект и должен возвращать массив с именами всех переменных этого объекта, которые должны быть сериализованы. Если метод ничего не возвращает, онnull
сериализуется и E_NOTICE
выдается.
Примечание :
__sleep () не может возвращать имена частных свойств в родительских классах. Это приведет к
E_NOTICE
ошибке уровня. Вместо этого используйте __serialize() .
Предполагаемое использование __sleep() состоит в том, чтобы зафиксировать ожидающие данные или выполнить аналогичные задачи очистки. Также функция полезна, если очень большие объекты не нужно сохранять полностью.
И наоборот, unserialize() проверяет наличие функции с магическим именем __wakeup() . Если она присутствует, эта функция может восстановить любые ресурсы, которые может иметь объект.
Предполагаемое использование __wakeup() состоит в том, чтобы восстановить любые соединения с базой данных, которые могли быть потеряны во время сериализации, и выполнить другие задачи повторной инициализации.
Пример #1 Сон и пробуждение
<?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();
}
}?>
__serialize() и __unserialize()
public __serialize(): array
public __unserialize(array $data): void
serialize() проверяет, есть ли в классе функция с магическим именем __serialize() . Если это так, эта функция выполняется до любой сериализации. Он должен создать и вернуть ассоциативный массив пар ключ/значение, представляющий сериализованную форму объекта. Если массив не возвращается, будет выброшена ошибка TypeError .
Примечание :
Если и __serialize() , и __sleep() определены в одном и том же объекте, будет вызываться только __serialize() . __sleep() будет игнорироваться. Если объект реализует интерфейс Serializable , метод интерфейса
serialize()
будет проигнорирован и вместо него будет использоваться __serialize() .
Предполагаемое использование __serialize() состоит в том, чтобы определить удобное для сериализации произвольное представление объекта. Элементы массива могут соответствовать свойствам объекта, но это не обязательно.
И наоборот, unserialize() проверяет наличие функции с магическим именем __unserialize() . Если он присутствует, этой функции будет передан восстановленный массив, который был возвращен из __serialize() . Затем он может восстановить свойства объекта из этого массива по мере необходимости.
Примечание :
Если и __unserialize() , и __wakeup() определены в одном и том же объекте, будет вызываться только __unserialize() . __wakeup() будет игнорироваться.
Примечание :
Эта функция доступна начиная с PHP 7.4.0.
Пример #2 Сериализация и десериализация
<?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 __serialize(): array
{
return [
'dsn' => $this->dsn,
'user' => $this->username,
'pass' => $this->password,
];
}
public function __unserialize(array $data): void
{
$this->dsn = $data['dsn'];
$this->username = $data['user'];
$this->password = $data['pass'];
$this->connect();
}
}?>
__toString()
public __toString(): string
Метод __toString() позволяет классу решить, как он будет реагировать, когда с ним будут обращаться как со строкой. Например, что echo $obj;
будет печатать.
Предупреждение
Начиная с PHP 8.0.0, возвращаемое значение соответствует стандартной семантике типов PHP, что означает, что оно будет преобразовано в строку , если это возможно, и если строгая типизация отключена.
Начиная с PHP 8.0.0, любой класс, содержащий метод __toString() , также будет неявно реализовывать интерфейс Stringable и, таким образом, будет проходить проверку типа для этого интерфейса. В любом случае рекомендуется явно реализовать интерфейс.
В PHP 7.4 возвращаемое значение должно быть строкой , иначе выдается ошибка .
До PHP 7.4.0 возвращаемое значение должно быть строкой , в противном случае выдается фатальная E_RECOVERABLE_ERROR
ошибка.
Предупреждение
До версии PHP 7.4.0 было невозможно создать исключение из метода __toString() . Это приведет к фатальной ошибке.
Пример #3 Простой пример
<?php
// Declare a simple class
class TestClass
{
public $foo;
public function __construct($foo)
{
$this->foo = $foo;
}
public function __toString()
{
return $this->foo;
}
}
$class = new TestClass('Hello');
echo $class;
?>
__invoke()
__invoke( ...$values): mixed
Метод __invoke() вызывается, когда скрипт пытается вызвать объект как функцию.
Пример #4 Использование __invoke()
<?php
class CallableClass
{
public function __invoke($x)
{
var_dump($x);
}
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>
__set_state()
static __set_state(array $properties): object
Этот статический метод вызывается для классов, экспортируемых функцией var_export() .
Единственным параметром этого метода является массив, содержащий экспортируемые свойства в виде ['property' => value, ...]
.
Пример #5 Использование __set_state()
<?php
class A
{
public $var1;
public $var2;
public static function __set_state($an_array)
{
$obj = new A;
$obj->var1 = $an_array['var1'];
$obj->var2 = $an_array['var2'];
return $obj;
}
}
$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';
$b = var_export($a, true);
var_dump($b);
eval('$c = ' . $b . ';');
var_dump($c);
?>
Приведенный выше пример выведет:
string(60) "A::__set_state(array(
'var1' => 5,
'var2' => 'foo',
))"
object(A)#2 (2) {
["var1"]=>
int( 5)
["var2"]=>
строка(3) "foo"
}
Примечание . При экспорте объекта var_export() не проверяет, реализовано ли __set_state() классом объекта, поэтому повторный импорт объектов приведет к исключению ошибки , если __set_state() не реализовано. В частности, это влияет на некоторые внутренние классы. Программист должен убедиться, что повторно импортируются только те объекты, класс которых реализует __set_state().
__debugInfo()
__debugInfo (): array
Этот метод вызывается функцией var_dump() при сбросе объекта для получения свойств, которые должны быть показаны. Если метод не определен для объекта, будут показаны все общедоступные, защищенные и частные свойства.
Пример #6 Использование __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));
?>
0 комментариев