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

Магічні методи – це спеціальні методи, які перевизначають дію 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. До 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()

Зауваження :

Починаючи з PHP 8.0.0, повернення значення, що не є масивом, з __sleep() призводить до попередження. Раніше видавалося повідомлення.

Предполагаемое использование__sleep() полягає в завершенні роботи над даними, що чекають на обробку або інших подібних завдань очищення. Крім того, цей метод може бути корисним, коли є дуже великі об'єкти, які немає потреби повністю зберігати.

З іншого боку, функція unserialize() перевіряє наявність методу з магічним ім'ям __wakeup(). Якщо є, ця функція може відновлювати будь-які ресурси, які може мати об'єкт.

Предполагаемое использование__wakeup() полягає у відновленні будь-яких з'єднань з базою даних, які могли бути втрачені під час операції серіалізації та виконання інших операцій повторної ініціалізації.

Приклад #1 Серіалізація та десеріалізація

Loading...

__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 Серіалізація та десеріалізація

Loading...

__toString()

public __toString(): string

Метод__toString() дозволяє класу вирішувати, як він повинен реагувати при перетворенні на рядок. Наприклад, що вивести під час виконання echo $obj;

Увага

Починаючи з PHP 8.0.0, значення, що повертається слід стандартній семантиці типу PHP, що означає, що воно буде перетворено в рядок (string), якщо можливо, і якщо strict typing вимкнено.

Об'єкт, що реалізує Stringable не буде прийматись оголошенням типу string, якщо включена сувора типізація. Якщо така поведінка необхідна, то оголошення типу має приймати інтерфейс. Stringable та рядок (string) за допомогою об'єднання типів.

Начиная с PHP 8.0.0, любой класс, содержащий метод__toString(), також неявно реалізовуватиме інтерфейс Stringable і, таким чином, проходитиме перевірку типу для цього інтерфейсу У будь-якому випадку рекомендується явно реалізувати інтерфейс.

В PHP 7.4 возвращаемое значениеПОВИННО бути рядком (string), інакше видається Error

До PHP 7.4.0 возвращаемое значениеповинно бути рядком (string), інакше видається фатальна помилка **E_RECOVERABLE_ERROR**is emitted.

Увага

Не можна викинути виняток із методу __toString() до PHP 7.4.0. Це призведе до фатальної помилки.

Приклад #3 Простий приклад

Loading...

Результат виконання наведеного прикладу:

Привет

__invoke()

__invoke( ...$values): mixed

Метод__invoke() викликається, коли скрипт намагається виконати об'єкт як функцію.

Приклад #4 Использование__invoke()

Loading...

Результат виконання наведеного прикладу:

int(5)
bool(true)

Приклад #5 Приклад использования__invoke()

Loading...

Результат виконання наведеного прикладу:

Array
(
    [0] => Array
        (
            [id] => 3
            [first_name] => Alice
            [last_name] => Gustav
        )

    [1] => Array
        (
            [id] => 2
            [first_name] => Bob
            [last_name] => Filipe
        )

    [2] => Array
        (
            [id] => 1
            [first_name] => John
            [last_name] => Do
        )

)
Array
(
    [0] => Array
        (
            [id] => 1
            [first_name] => John
            [last_name] => Do
        )

    [1] => Array
        (
            [id] => 2
            [first_name] => Bob
            [last_name] => Filipe
        )

    [2] => Array
        (
            [id] => 3
            [first_name] => Alice
            [last_name] => Gustav
        )

)

__set_state()

static __set_state(array $properties): object

Цей статичний метод викликається тим класів, які експортуються функцією var_export()

Єдиним параметром цього методу є масив, що містить властивості, що експортуються у вигляді ['property' => value, ...]

Приклад #6 Использование__set_state()

Loading...

Результат виконання наведеного прикладу:

string(60) "A::__set_state(array(
   'var1' => 5,
   'var2' => 'foo',
))"
object(A)#2 (2) {
  ["var1"]=>
  int(5)
  ["var2"]=>
  string(3) "foo"
}

Зауваження: Під час експорту об'єкту var_export() не перевіряє, чи реалізує клас об'єкта метод __set_state()тому повторний імпорт об'єктів призведе до виключення Error, якщо метод __set_state() не реалізовано. Зокрема, це стосується деяких внутрішніх класів. Необхідність перевірки, чи реалізує імпортований клас метод __set_state(), повністю лежить на розробнику.

__debugInfo()

__debugInfo(): array

Цей метод викликається функцією var_dump(), коли потрібно вивести список властивостей об'єкта. Якщо цей метод не визначений, тоді будуть виведені всі властивості об'єкта з модифікаторами public, protected та private.

Приклад #7 Использование__debugInfo()

Loading...

Результат виконання наведеного прикладу:

object(C)#1 (1) {
  ["propSquared"]=>
  int(1764)
}