Магические методы PHP

Содержание
Названия этих функций зарезервированы – если создать функцию с одним из этих названий, функциональность магического метода будет ассоциироваться с вашим методом. Все магические методы должны объявляться как общедоступные.
Магическими эти методы называются по той причине, что они вызываются автоматически, если определить один из этих методов в классе, остаётся лишь определить, какую задачу будет выполнять метод. Лучший пример – функция __construct(), которая вызывается автоматически каждый раз при создании экземпляра объекта.
В общих словах, магические методы PHP позволяют выполнять различные операции с объектами. Кроме того, они позволяют обрабатывать определённые типы событий при помощи манипуляции объектами.
Далее мы кратко рассмотрим все магические методы, доступные в языке программирования PHP.
Метод __construct()
При определении этого метода в классе, функция будет автоматически вызываться во время создания каждого экземпляра класса. Назначение метода – передача объекту начальных параметров, используемых по умолчанию. Этот метод иногда называют конструктором (constructor).
Вот пример использования этого метода:
class Student { private $name; private $email; public function __construct($name, $email) { $this->name = $name; $this->email = $email; } } $objStudent = new Student('John', 'john@tutsplus.com');
В данном примере во время создания нового объекта Student
происходит первый вызов метода __construct()
и с его помощью передаются значения объекту для некоторых из его свойств.
Метод __destruct()
Метод __destruct()
называется деструктором, и вызывается во время уничтожения объекта. Обычно это происходит после остановки или завершения скрипта. Назначение метода – предоставить разработчику возможность сохранить состояние объекта или выполнить какое-то другое действие, следующее за завершением сценария.
Вариант использования:
class Student { private $name; private $email; public function __construct($name, $email) { $this->name = $name; $this->email = $email; } public function __destruct() { echo 'Вызывается во время уничтожения объекта...'; // сохранение состояния объекта или другие действия } } $objStudent = new Student('John', 'john@tutsplus.com');
Метод __set()
Магический метод __set()
вызывается при попытке присвоить данные недоступным или несуществующим свойствам объекта. Назначение этого метода – задание дополнительных данных объекта, для явно не определены свойства.
Метод работает следующим образом:
class Student { private $data = array(); public function __set($name, $value) { $this->data[$name] = $value; } } $objStudent = new Student(); // вызов __set() $objStudent->phone = '0491 570 156';
В приведённом примере была попытка создать несуществующее свойство phone
. В результате происходит вызов __set()
. В качестве первого аргумента метода __set()
выступает название задаваемого свойства, вторым аргументом выступает значение для этого свойства.
Метод __get()
Если __set()
используется для задания значений несуществующих свойств, то __get()
выполняет противоположную функцию. Этот метод вызывается в случае, если код пытается считать данные из несуществующих или недоступных свойств объекта. Назначение метода – предоставить значения таким свойствам.
На практике это выглядит следующим образом:
class Student { private $data = array(); public function __set($name, $value) { $this->data[$name] = $value; } public function __get($name) { If (isset($this->data[$name])) { return $this->data[$name]; } } } $objStudent = new Student(); // вызов __set() $objStudent->phone = '0491 570 156'; //вызов __get() echo $objStudent->phone;
Метод __toString()
Позволяет определить, что именно вывести на экран в том случае, если объект обрабатывается, как строка. К примеру, если не применить __toString()
для объекта, который используется echo
или print
, возникнет ошибка при вызове echo $objStudent
.
Рассмотрим на примере:
class Student { private $name; private $email; public function __construct($name, $email) { $this->name = $name; $this->email = $email; } public function __toString() { return 'Student name: '.$this->name . '<br>' . 'Student email: '.$this->email; } } $objStudent = new Student('John', 'john@tutsplus.com'); echo $objStudent;
Здесь во время вывода echo
объект $objStudent
вызывает метод __toString()
. Внутри этого метода определено, что нужно вывести на экран. Если этого не сделать, то во время исполнения кода произойдёт ошибка.
Методы __call() и __callStatic()
Если методы __get()
и __set()
используются в случае обращения к несуществующим свойствам, то метод __call()
вызывается при попытке использования недоступных методов, которые ещё не определены классе.
class Student { public function __call($methodName, $arguments) { // $methodName = getStudentDetails // $arguments = array('1') } } $objStudent = new Student(); $objStudent->getStudentDetails(1);
Как можно заметить, в приведённом выше примере есть попытка вызвать метод getStudentDetails()
, который ещё не определён, что приводит к вызову __call()
. В качестве первого аргумента выступает название вызываемого метода, второй аргумент состоит из списка значений, передаваемых методу.
Метод __callStatic()
очень похож на __call()
, за единственным исключением: он вызывается в случае обращения к несуществующим методам в статическом контексте. Таким образом, если есть попытка обратиться к неопределённому статическому объекту – используется __callStatic()
.
Методы __isset() и __unset()
Магический метод __isset()
вызывается в случае, если код использует isset()
для обращения к несуществующим (или недоступным) свойствам объекта.
Посмотрим, как это выглядит на практике:
class Student { private $data = array(); public function __isset($name) { return isset($this->data[$name]); } } $objStudent = new Student(); echo isset($objStudent->phone);
В этом фрагменте свойство phone
не определено в объекте, что приводит к вызову метода __isset()
.
Метод __unset()
, в свою очередь, вызывается в том случае, если выполняется вызов unset()
для свойств объекта, которые в данный момент не определены или недоступны.
Методы __sleep() и __wakeup()
Магический метод __sleep()
отличается от функций, которые были рассмотрены выше. Этот метод вызывается во время обращения к объекту с помощью функции serialize()
.
В случае очень большого объекта требуется сохранить лишь выбранные свойства во время сериализации и после этого закрыть объект. Метод __sleep()
в таком случае возвращает массив с именами всех свойств объекта, которые должны быть сериализированы (преобразованы в специальную строку).
Посмотрим, как можно применить этот метод:
class Student { private $name; private $email; private $phone; private $db_connection_link; public function __construct($name, $email, $phone) { $this->name = $name; $this->email = $email; $this->phone = $phone; } public function __sleep() { return array('name', 'email', 'phone'); } public function __wakeup() { $this->db_connection_link = your_db_connection_function(); } }
В данном примере во время получения данных из объекта Student
, он вызывает метод __sleep()
. В результате сохраняются только нужные значения переменных – имя, адрес электронной почты, номер телефона (name
, email
, phone
).
С другой стороны, магический метод __wakeup()
используется для восстановления связей с объектами и выполнения заданий после того, как передача данных (сериализация) закончена и для объекта вызывается функция unserialize()
.
Метод __invoke()
Это особый метод – он используется в том случае, когда объект вызывается в качестве функции. Сначала мы посмотрим, как __invoke()
работает, а затем обсудим его назначение.
class Student { private $name; private $email; public function __construct($name, $email) { $this->name = $name; $this->email = $email; } public function __invoke() { echo 'Объект Student вызывается в качестве функции'; } } $objStudent = new Student('John', 'john@tutsplus.com'); $objStudent();
Как можно увидеть в этом примере, код вызывает объект $objStudent
, как функцию. Поскольку мы используем метод __invoke()
, это действие не приведёт к ошибке. В этом и заключается назначение метода __invoke()
– он позволяет нам вызывать объекты так же, как функции.
Метод __clone()
Для создания копии существующего объекта можно использовать команду clone
. Однако если нужно изменить свойства скопированного объекта после клонирования, следует определить в классе магический метод __clone()
:
<?php Class Student_School { } class Student { private $name; private $email; private $object_student_school; public function __construct() { $this->object_student_school = new Student_School(); } public function __clone() { $this->object_student_school = clone $this->object_student_school; } } $objStudentOne = new Student(); $objStudentTwo = clone $objStudentOne;
Приведённый выше фрагмент кода на первом этапе создаёт поверхностную копию объекта – как следствие, вложенные объекты при этом не копируются. В контексте данного примера, если бы мы не использовали метод __clone()
, копия объекта, $objStudentTwo
, по-прежнему указывала бы на объект Student_School
, на который ссылается оригинал, $objStudentOne
. Однако использование магического метода __clone()
обеспечивает нам копирование Student_School
вместе с главным объектом.
Метод __debugInfo()
Этот магический метод вызывается при попытке вызова объекта с помощью функции var_dump()
. Если вы не определили __debugInfo()
в своем классе, он выведет все общедоступные, частные и защищённые свойства. Если же нужно ограничить информацию, отображаемую при выводе, используется этот метод.
class Student { public $name; private $email; private $ssn; public function __debugInfo() { return array('student_name' => $this->name); } } $objStudent = new Student(); var_dump($objStudent); // object(Student)#1 (1) { ["student_name"]=> NULL }
Данный метод возвращает массив, состоящий из ключей и значений, которые будут отображаться в то время, когда функция var_dump()
вызывается для объекта. Это даёт возможность полностью контролировать отображение данных, которые отображаются на экране в ходе вызова функции var_dump()
.
Метод __set_state()
Это статический метод, который используется в связке с функцией var_export()
. Данная функция выводит структурированную информацию о переменной. Если используется функция var_export()
для экспорта класса, то необходимо определить в нем метод __set_state()
:
class Student { public $name; private $email; public function __construct($name, $email) { $this->name = $name; $this->email = $email; } public static function __set_state(array $array) { $obj = new Student; $obj->name = $array['name']; $obj->email = $array['email']; return $obj; } } $objStudent = new Student('John','John@yahoo.com'); var_export($objStudent); // Output: Student::__set_state(array( 'name' => 'John', 'email' => 'John@yahoo.com', ))
Как можно заметить, экспортируемая строка представляет собой валидный PHP-код, который в случае необходимости можно использовать для создания объекта.
Заключение
В этой статье рассмотрены все магические методы, доступные в PHP. Использование каждого метода было проиллюстрировано примером кода. Надеюсь, что эта статья пригодится в качестве референса или подсказки во время работы над разнообразными PHP-проектами.