Загрузка...

Магические методы __get() и __set() в php

php

В PHP магические методы __get() и __set() позволяют перехватывать обращение к несуществующим или недоступным свойствам объекта. Давайте разберем их работу подробно.

Метод __get()

Вызывается при чтении значения недоступного свойства

public mixed __get(string $name)

Пример использования:

class User {
    private $data = [];

    public function __get($name) {
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }

        return "Свойство {$name} не существует";
    }
}

$user = new User();
echo $user->name; // Вызовет __get('name')

Метод __set()

Вызывается при записи значения в недоступное свойство

public void __set(string $name, mixed $value)

Пример использования:

class User {
    private $data = [];

    public function __set($name, $value) {
        $this->data[$name] = $value;
    }

    public function __get($name) {
        return $this->data[$name] ?? null;
    }
}

$user = new User();
$user->name = 'John'; // Вызовет __set('name', 'John')
echo $user->name;     // Вызовет __get('name') → 'John'

Практический пример

class Config {
    private $settings = [];

    public function __set($name, $value) {
        $this->settings[$name] = $value;
    }

    public function __get($name) {
        return $this->settings[$name] ?? null;
    }

    public function getAll() {
        return $this->settings;
    }
}

$config = new Config();
$config->db_host = 'localhost';
$config->db_user = 'root';
$config->db_pass = 'password';

echo $config->db_host; // localhost
print_r($config->getAll());

Более сложный пример с валидацией

class Product {
    private $data = [];
    private $allowedProperties = ['name', 'price', 'category'];

    public function __set($name, $value) {
        if (!in_array($name, $this->allowedProperties)) {
            throw new Exception("Свойство {$name} не разрешено");
        }

        // Валидация для price
        if ($name === 'price' && (!is_numeric($value) || $value < 0)) {
            throw new Exception("Цена должна быть положительным числом");
        }

        $this->data[$name] = $value;
    }

    public function __get($name) {
        if (!array_key_exists($name, $this->data)) {
            throw new Exception("Свойство {$name} не установлено");
        }

        return $this->data[$name];
    }
}

$product = new Product();
$product->name = "Телефон";
$product->price = 1000;
// $product->invalid = "test"; // Выбросит исключение

Когда использовать __get() и __set()

  1. Динамические свойства — когда свойства определяются во время выполнения
  2. Обертка для массивов — для объектного доступа к элементам массива
  3. Прокси-объекты — для делегирования вызовов другим объектам
  4. ORM и Active Record — для доступа к данным базы как к свойствам объекта

Важные особенности

  • Методы вызываются только для недоступных свойств (private, protected или несуществующих)
  • Не работают для статических свойств
  • Могут негативно влиять на производительность при частом использовании
  • Усложняют статический анализ кода

Альтернативный подход с __call()

Для методов существует аналогичная пара магических методов — __call() и __callStatic().

class Magic {
    public function __call($name, $arguments) {
        echo "Вызван метод: {$name} с аргументами: ";
        print_r($arguments);
    }
}

$obj = new Magic();
$obj->undefinedMethod('test'); // Вызовет __call()

Магические методы предоставляют мощный инструмент для создания гибких и динамических объектов, но их следует использовать осознанно, так как они могут сделать код менее предсказуемым.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *