Магические методы 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(). В результате сохраняются только нужные значения переменных – имя, адрес электронной почты, номер телефона (nameemailphone).

С другой стороны, магический метод __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-проектами.

Написать комментарий