Шпаргалка по магическим методам 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-проектами.