Ответ
Да, метод __set() будет вызван автоматически при попытке присвоить значение недоступному или несуществующему свойству объекта.
Условия срабатывания:
- Свойство объявлено как
privateилиprotected. - Свойство не существует в классе.
- Вызов происходит в контексте объекта (не статически).
Пример:
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(). Если, конечно, ты его предусмотрел.
Когда это срабатывает, блядь:
- Свойство объявлено как
privateилиprotected— то есть, ты снаружи к нему в лоб не подойдёшь. - Свойства вообще нет в классе — ты его с потолка взял.
- И самое главное — вызываешь ты это в контексте объекта, а не статически. Иначе будет тебе хиросима, а не магия.
Смотри, вот живой пример, как это обычно юзают:
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, требует, чтобы ты понимал, что делаешь. А то можно так наворотить, что потом сам от себя охуеешь, когда это всё начнёт падать в три часа ночи.