Ответ
Непосредственно в момент вызова __set($property, $value) другие магические методы не вызываются автоматически. Однако в типичном сценарии использования часто работает связка с методом __get().
Типичный паттерн — хранение данных в приватном массиве:
class Config implements ArrayAccess
{
private array $data = [];
private array $accessed = []; // Трекер обращений
public function __get(string $name): mixed
{
echo "__get() вызван для '$name'.n";
$this->accessed[$name] = true;
return $this->data[$name] ?? null;
}
public function __set(string $name, mixed $value): void
{
echo "__set() вызван для '$name'.n";
$this->data[$name] = $value;
}
}
$config = new Config();
$config->timeout = 30; // Только __set()
echo $config->timeout; // Сначала __get(), потом вывод значения
Когда может вызваться __isset()?
Метод __isset() может быть вызван до __set(), если в коде есть проверка существования свойства через isset() или empty() перед присваиванием.
if (!isset($obj->newProperty)) {
// Здесь вызовется __isset('newProperty')
$obj->newProperty = 'value'; // Затем вызовется __set()
}
Таким образом, __set() работает в паре с __get() для реализации динамических свойств, а __isset() и __unset() дополняют эту функциональность.
Ответ 18+ 🔞
Давай разберём эту магию, а то некоторые думают, что в PHP всё само по себе взлетает и летает. Как будто на дворе 2002-й год и можно просто написать $obj->prop = 5, а там за кулисами целый цирк с конями начинается.
Смотри, вот в чём прикол. Когда ты пишешь $config->timeout = 30;, то вызывается только __set(). Никакой __get, __isset или __unset тут автоматически не дергается. Это как прийти в пустую квартиру и просто поставить свой стул — ты ни у кого не спрашиваешь разрешения, просто ставишь. __set() — это и есть твой грузчик, который заносит этот стул.
Но вся ебля начинается, когда ты потом пытаешься этот стул забрать или спросить, а он вообще тут есть? Вот типичная схема работы умных объектов, которые хранят данные в приватном массиве:
class Config implements ArrayAccess
{
private array $data = [];
private array $accessed = []; // Трекер обращений
public function __get(string $name): mixed
{
echo "__get() вызван для '$name'.n";
$this->accessed[$name] = true;
return $this->data[$name] ?? null;
}
public function __set(string $name, mixed $value): void
{
echo "__set() вызван для '$name'.n";
$this->data[$name] = $value;
}
}
$config = new Config();
$config->timeout = 30; // Только __set() — грузчик занёс стул
echo $config->timeout; // А вот тут сначала __get() (грузчик ищет стул), потом вывод значения
Видишь? Присвоил — __set(). Прочитал — __get(). Всё логично, как в аптеке.
А вот где может вылезти __isset()?
Представь себе хитрожопого разработчика, который перед тем, как что-то записать, любит всё проверить. Он напишет какую-нибудь параноидальную хуйню:
if (!isset($obj->newProperty)) {
// Здесь вызовется __isset('newProperty') — типа "а стул-то тут уже есть?"
$obj->newProperty = 'value'; // И только потом вызовется __set() — "ладно, ставлю свой"
}
Вот и получается, что __set() — это основной мужик с молотком, который забивает гвозди. __get() — это его напарник, который эти гвозди потом ищет. А __isset() и __unset() — это такие надзиратели, которые могут прийти перед этим и спросить: "А гвоздь-то тут уже есть? А можно его вообще выдернуть?".
Так что никакой автоматической магии, кроме вызова самого __set(), нет. Всё остальное — это уже твои ручные проверки или логика внутри других методов, которые ты сам и вызываешь. Просто запомни: положил — __set(), взял — __get(), спросил "есть?" — __isset(), сказал "убери нахуй" — __unset(). Ёпта, даже ребёнку понятно.