Сработает ли магический метод __set() при присвоении значения свойству класса?

Ответ

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

Условия срабатывания:

  1. Свойство объявлено как private или protected.
  2. Свойство не существует в классе.
  3. Вызов происходит в контексте объекта (не статически).

Пример:

class UserSettings {
    private array $storage = [];

    public function __set(string $name, mixed $value): void {
        // Логируем или валидируем перед записью
        if ($name === 'email' && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException('Invalid email');
        }
        $this->storage[$name] = $value;
    }

    public function __get(string $name): mixed {
        return $this->storage[$name] ?? null;
    }
}

$settings = new UserSettings();
$settings->email = 'user@example.com'; // Вызовет __set()
$settings->theme = 'dark'; // Также вызовет __set()
echo $settings->email; // Вызовет __get()

Важные нюансы:

  • Для public-свойств __set() не вызывается.
  • Метод должен быть объявлен как public.
  • Часто используется для:
    • Реализации динамических свойств (как в примере выше).
    • Валидации данных перед записью.
    • Логирования изменений свойств.
    • Проксирования запросов к внешнему хранилищу.
  • В отличие от __get(), который может вызываться и при чтении, __set() работает только на запись.

Ответ 18+ 🔞

А, ну это же про тот самый волшебный метод __set()! Давай разберём, как он работает, а то у меня тут один чувак на днях с ним так накосячил, что я чуть не поседел, ёпта.

В общем, представь себе такую картину: у тебя есть объект, и ты пытаешься запихнуть в него значение, как будто это обычное свойство. А свойство-то либо закрытое (private/protected), либо его вообще в природе не существует. Вот тут-то PHP и кричит: «Э, сабака сука, куда лезешь?» — и вместо того, чтобы выдать фатальную ошибку и послать тебя нахуй, он вежливо стучится в метод __set(). Если, конечно, ты его предусмотрел.

Когда это срабатывает, блядь:

  1. Свойство объявлено как private или protected — то есть, ты снаружи к нему в лоб не подойдёшь.
  2. Свойства вообще нет в классе — ты его с потолка взял.
  3. И самое главное — вызываешь ты это в контексте объекта, а не статически. Иначе будет тебе хиросима, а не магия.

Смотри, вот живой пример, как это обычно юзают:

class UserSettings {
    private array $storage = [];

    public function __set(string $name, mixed $value): void {
        // Тут можно, например, проверить, что за хуйню ты пытаешься записать
        if ($name === 'email' && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException('Invalid email');
        }
        $this->storage[$name] = $value;
    }

    public function __get(string $name): mixed {
        return $this->storage[$name] ?? null;
    }
}

$settings = new UserSettings();
$settings->email = 'user@example.com'; // Вызовет __set()
$settings->theme = 'dark'; // Также вызовет __set()
echo $settings->email; // Вызовет __get()

Видишь? Мы создали объект, а потом просто начали в него пихать значения, как в обычный массив. А под капотом __set() всё аккуратненько складывает в приватный массив $storage. Удобно, да? Но есть нюансы, блядь.

Важные моменты, которые надо помнить, а то будет пиздец:

  • Если свойство public — то никакой __set() не вызовется. PHP просто запишет значение и скажет «да похуй».
  • Сам метод __set() должен быть public, иначе это будет манда с ушами, а не магия.
  • Чаще всего его используют для:
    • Создания динамических свойств на лету — как в примере выше, это же ебать мои старые костыли, удобно!
    • Чтобы проверить данные перед записью — типа, не пытаешься ли ты в age записать строку «банан».
    • Чтобы залогировать, кто и когда что менял — для параноиков.
    • Или чтобы проксировать запрос куда-то на сторону — в базу, в кэш, в облако, хуй знает куда.
  • И главное, не путай с __get()! __set() работает только на запись. Когда ты читаешь несуществующее свойство — вызывается __get(). А когда пишешь — вот тогда уже __set().

В общем, инструмент мощный, но, как и всё в PHP, требует, чтобы ты понимал, что делаешь. А то можно так наворотить, что потом сам от себя охуеешь, когда это всё начнёт падать в три часа ночи.