Магический метод 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
.