Шпаргалка по магическим методам PHP
В этой статье вы найдете краткое описание всех магических методов, доступных в PHP. Независимо от того, являетесь ли вы опытным PHP-разработчиком, или начинающим, – если вам приходилось иметь дело с объектно-ориентированным программированием на PHP, вы уже сталкивались, по крайней мере, с некоторыми из магических методов.
Если же вы раньше не слышали об этих методах, позвольте мне их представить. Следующие PHP-функции называются магическими:
- __construct(),
- __destruct(),
- __call(),
- __callStatic(),
- __get(),
- __set(),
- __isset(),
- __unset(),
- __sleep(),
- __wakeup(),
- __toString(),
- __invoke(),
- __set_state(),
- __clone(),
- __debugInfo().
Названия этих функций зарезервированы – если вы дадите своей собственной функции одно из этих названий, функциональность магического метода будет ассоциироваться с вашим методом. Все магические методы должны объявляться как общедоступные.
Магическими эти методы называются по той причине, что они вызываются автоматически, если вы определите один из этих методов в классе. Вам остается лишь определить, какую задачу будет выполнять метод. Лучший пример – функция __construct(), которая вызывается автоматически каждый раз при создании экземпляра объекта.
В общих словах, магические методы PHP позволяют выполнять различные операции с объектами. Кроме того, они позволяют обрабатывать определенные типы событий при помощи манипуляции объектами.
Магические PHP методы
Далее мы кратко рассмотрим все магические методы, доступные в языке программирования PHP.
Метод __construct()
При определении этого метода в классе, функция будет автоматически вызываться во время создания каждого экземпляра класса. Назначение метода – передача объекту начальных параметров, используемых по умолчанию. Этот метод иногда называют конструктором (constructor).
Вот пример использования этого метода:
<?php
class Student {
private $name;
private $email;
public function __construct($name, $email)
{
$this->name = $name;
$this->email = $email;
}
}
$objStudent = new Student('John', 'john@tutsplus.com');
?>
В данном примере во время создания нового объекта с параметрами new student('John','john@tutsplus.com'), происходит первый вызов метода __construct(). С помощью __construct() мы передаем объекту значения для некоторых из его свойств.
Метод __destruct()
Метод __destruct() называется деструктором, и вызывается во время уничтожения объекта. Обычно это происходит после остановки или завершения скрипта. Назначение метода – предоставить разработчику возможность сохранить состояние объекта или выполнить какое-то другое действие, следующее за завершением сценария.
Вариант использования:
<?php
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() вызывается при попытке присвоить данные недоступным или несуществующим свойствам объекта. Назначение этого метода – задание дополнительных данных объекта, для которых вы явно не определили свойства.
Метод работает следующим образом:
<?php
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() выполняет противоположную функцию. Этот метод вызывается в случае, если код пытается считать данные из несуществующих или недоступных свойств объекта. Назначение метода – предоставить значения таким свойствам.
На практике это выглядит следующим образом:
<?php
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, возникнет ошибка.
Рассмотрим на примере:
<?php
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() вызывается при попытке использования недоступных методов, которые вы еще не определили в своем классе.
<?php
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() для обращения к несуществующим (или недоступным) свойствам объекта. Посмотрим, как это выглядит на практике:
<?php
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() в таком случае возвращает массив с именами всех свойств объекта, которые должны быть сериализированы (преобразованы в специальную строку).
Посмотрим, как можно применить этот метод:
<?php
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() работает, а затем обсудим его назначение.
<?php
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() в своем классе, он выведет все общедоступные, частные и защищенные свойства. Поэтому, если вы хотите ограничить информацию, отображаемую при сбросе, используйте этот метод.
<?php
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():
<?php
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-проектами.