__get, __set, __isset, __unset
Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy — урок 46 из 91.
PHP предоставляет четыре магических метода, которые перехватывают доступ к свойствам: __get(), __set(), __isset() и __unset(). Они срабатывают, когда вы пытаетесь получить доступ к свойствам, которые не существуют или недоступны.
Метод __get() вызывается при чтении недоступного свойства, в то время как __set() обрабатывает запись в него. Это позволяет создавать динамические свойства или добавлять логику при обращении к свойствам:
<?php
class DynamicObject {
private array $data = [];
public function __get(string $name): mixed {
return $this->data[$name] ?? null;
}
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
}
$obj = new DynamicObject();
$obj->title = "Hello";
$obj->count = 42;
echo $obj->title . " - " . $obj->count;
Вывод:
Hello - 42Метод __isset() вызывается при использовании isset() или empty(), а __unset() реагирует на функцию unset():
<?php
class DynamicObject {
private array $data = [];
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
public function __isset(string $name): bool {
return isset($this->data[$name]);
}
public function __unset(string $name): void {
unset($this->data[$name]);
}
}
$obj = new DynamicObject();
$obj->name = "Test";
echo isset($obj->name) ? "exists" : "missing";
Вывод:
existsЭти методы обычно используются для создания гибких контейнеров данных, реализации ленивой загрузки или создания объектов, которые ведут себя как массивы, сохраняя при этом объектно-ориентированную структуру.
Задание
ЛегкоДавайте создадим гибкий менеджер конфигурации, который динамически сохраняет настройки с помощью магических методов. Ваш класс будет перехватывать доступ к свойствам для управления значениями конфигурации, проверки существования настроек и их удаления при необходимости — и все это без явного определения каждого свойства.
Вы организуете свой код в двух файлах:
Config.php— Создайте классConfig, который использует приватный массив для внутреннего хранения значений конфигурации. Реализуйте все четыре магических метода для работы со свойствами:__get($name)— Возвращает значение для данного ключа или"undefined", если ключ не существует__set($name, $value)— Сохраняет значение под данным ключом__isset($name)— Возвращает, существует ли ключ в конфигурации__unset($name)— Удаляет ключ из конфигурации
count(), который возвращает количество сохраненных настроек.main.php— Подключите файл Config. Вы получите три входных значения: имя настройки, значение настройки и второе имя настройки. Создайте экземплярConfigи выполните следующие операции:- Установите первую настройку в заданное значение
- Выведите, существует ли первая настройка, используя
isset()— выведите"exists"или"missing" - Выведите значение первой настройки
- Выведите текущее количество настроек
- Используйте
unset(), чтобы удалить первую настройку - Выведите, существует ли первая настройка теперь — выведите
"exists"или"missing" - Выведите значение второй настройки (которая никогда не была установлена)
Каждый вывод должен быть на отдельной строке. Магические методы позволяют вам взаимодействовать с объектом Config, используя естественный синтаксис свойств, такой как $config->theme = "dark" и isset($config->theme), даже если фактические свойства не определены.
Шпаргалка
PHP предоставляет четыре магических метода для перехвата доступа к свойствам:
__get(string $name): mixed— вызывается при чтении недоступного свойства__set(string $name, mixed $value): void— вызывается при записи в недоступное свойство__isset(string $name): bool— срабатывает при использованииisset()илиempty()__unset(string $name): void— срабатывает при использованииunset()
Пример использования __get() и __set():
<?php
class DynamicObject {
private array $data = [];
public function __get(string $name): mixed {
return $this->data[$name] ?? null;
}
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
}
$obj = new DynamicObject();
$obj->title = "Hello";
echo $obj->title; // Hello
Пример использования __isset() и __unset():
<?php
class DynamicObject {
private array $data = [];
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
public function __isset(string $name): bool {
return isset($this->data[$name]);
}
public function __unset(string $name): void {
unset($this->data[$name]);
}
}
$obj = new DynamicObject();
$obj->name = "Test";
echo isset($obj->name) ? "exists" : "missing"; // exists
Эти методы позволяют реализовать динамические свойства, ленивую загрузку и гибкие контейнеры данных, сохраняя при этом объектно-ориентированную структуру.
Попробуйте сами
<?php
require_once 'Config.php';
// Чтение входных данных
$settingName1 = trim(fgets(STDIN));
$settingValue = trim(fgets(STDIN));
$settingName2 = trim(fgets(STDIN));
// TODO: Создать экземпляр Config
// TODO: Установить первую настройку в заданное значение
// TODO: Вывести, существует ли первая настройка ("exists" или "missing")
// TODO: Вывести значение первой настройки
// TODO: Вывести текущее количество настроек
// TODO: Использовать unset() для удаления первой настройки
// TODO: Вывести, существует ли первая настройка сейчас ("exists" или "missing")
// TODO: Вывести значение второй настройки (которая никогда не была установлена)
?>В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово $thisМетодыСвойстваКонструктор (__construct)Деструктор (__destruct)Итоги — Простой калькулятор4Наследование
Основы наследованияКлючевое слово parent::Переопределение методовКлючевое слово finalАбстрактные классыИтоги — Иерархия сотрудников7Инкапсуляция
Public, Protected, PrivateПодробный разбор модификаторов доступаГеттеры и сеттерыСокрытие данныхConstructor Promotion (8.0)Итоги — Система учета студентов10Продвинутые концепции ООП
Композиция против наследованияВнедрение зависимостейАнонимные классыПеречисления (PHP 8.1)Файберы (PHP 8.1)Глубокое погружение в клонирование объектовГенераторы и итераторы13Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий2Пространства имен и автозагрузка
Введение в пространства именКлючевое слово useСтандарт автозагрузки PSR-4Автозагрузчик ComposerИтоги: структурированный проект5Интерфейсы и контракты
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовИнтерфейс против абстрактного классаType Hinting с интерфейсамиИтоги — Калькулятор фигур8Магические методы
Введение в магические методы__toString и __debugInfo__get, __set, __isset, __unset__call и __callStatic__clone и клонирование объектов__serialize и __unserializeИтоги — Кастомная коллекция11Система типов и обработка ошибок
Объявление типовNullable-типыТипы объединения и пересеченияКлассы исключенийИерархия пользовательских исключенийTry, Catch, FinallyИтоги — Валидатор форм14Проект: Управление библиотекой
Обзор проектаКлассы Book и User3Свойства классов
Свойства экземпляра и статические свойстваКонстанты в классахСтатические методы и свойстваПриватные и защищенные свойстваСвойства Readonly (PHP 8.1)Итоги — Менеджер банковского счета6Полиморфизм
Снова о переопределении методовПолиморфизм через интерфейсыType Hinting и Union TypesПозднее статическое связываниеИтоги — Payment Processor9Трейты
Введение в трейтыИспользование нескольких трейтовРазрешение конфликтов трейтовАбстрактные методы в трейтахТрейты и наследование12Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy