# Магический метод set

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

Давайте посмотрим на практическом примере. Пусть у нас дан вот такой класс `Test`:

`<?php class Test { private $prop1; private $prop2; } ?>`

Давайте сделаем в этом классе магический метод `__set`, который с помощью функции `var_dump` будет выводить имя свойства, к которому произошло обращение, и значение, которое этому свойству пытаются установить:

`<?php class Test { private $prop1; private $prop2; public function __set($property, $value) { var_dump($property . ' ' .$value); } } ?>`

Проверим работу нашего класса:

`<?php $test = new Test; $test->prop = 'value'; // var_dump метода __set выведет 'prop value' ?>`

Давайте теперь будем устанавливать значение свойству, имя которого хранится в переменной `$property`:

`<?php class Test { private $prop1; private $prop2; public function __set($property, $value) { $this->$property = $value; // устанавливаем значение } } ?>`

Теперь мы сможем записывать в приватные свойства снаружи класса:

`<?php $test = new Test; $test->prop1 = 1; // запишем 1 $test->prop2 = 2; // запишем 2 ?>`

Записывать мы можем, однако, проверить, записалось ли туда что-то - нет, так как свойства приватные.

Можно сделать геттер для этих свойств или просто воспользоваться магическим методом `__get`. Воспользуемся вторым вариантом:

`<?php class Test { private $prop1; private $prop2; public function __set($property, $value) { $this->$property = $value; } // Магический геттер свойств: public function __get($property) { return $this->$property; } } ?>`

Вот теперь мы можем проверить работу нашего класса. Проверим:

`<?php $test = new Test; $test->prop1 = 1; // запишем 1 $test->prop2 = 2; // запишем 2 echo $test->prop1; // выведет 1 echo $test->prop2; // выведет 2 ?>`

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

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

## Несуществующее свойство

Давайте попробуем записать данные в несуществующее свойство - это будет работать:

`<?php $test = new Test; $test->prop3 = 3; // запишем 3 echo $test->prop3; // выведет 3 ?>`

Пусть мы не хотим разрешать записывать в несуществующие свойства. И, вообще, хотим разрешить запись только в свойства `prop1` и `prop2`.

Это легко сделать - достаточно в методе `__set` добавить соответствующее условие:

`<?php class Test { private $prop1; private $prop2; public function __set($property, $value) { // Напишем условие: if ($property == 'prop1' or $property == 'prop2') { $this->$property = $value; } } public function __get($property) { return $this->$property; } } ?>`

Если таких свойств будет много, то не очень удобно перечислять их все в условии.

Давайте запишем разрешенные для записи свойства в массив и будем проверять наличие свойства в этом массиве с помощью функции `in_array`:

`<?php class Test { private $prop1; private $prop2; public function __set($property, $value) { $properties = ['prop1', 'prop2']; // разрешенные свойства if (in_array($property, $properties)) { $this->$property = $value; } } public function __get($property) { return $this->$property; } } ?>`

## Проверка при записи

Давайте будем проверять значения свойств на соответствие определенному условию:

`<?php class Test { private $prop1; private $prop2; public function __set($property, $value) { switch($property) { case 'prop1': // Если prop1 от 0 до 10: if ($value > 0 and $value < 10) { $this->$property = $value; } break; case 'prop2': // Если prop2 от 10 до 20: if ($value > 10 and $value < 20) { $this->$property = $value; } break; default: // Такого свойства нет break; } } public function __get($property) { return $this->$property; } } ?>`

## Применение

Практическое применение метода `__set` вы изучите самостоятельно, решив вот такую задачу:

Пусть дан вот такой класс `User` с геттерами и сеттерами свойств:

`<?php class User { private $name; private $age; public function getName() { return $this->name; } public function setName($name) { if ($name != '') { // проверяем имя на непустоту $this->name = $name; } } public function getAge() { return $this->age; } public function setAge($age) { if ($age >= 0 and $age <= 70) { // проверяем возраст $this->age = $age; } } } ?>`

Переделайте код этого класса так, чтобы вместо геттеров и сеттеров использовались магический методы `__get` и `__set`.

←→
↑