Запись свойств через магию в ООП в PHP

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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