Магические методы

//Магические методы — методы, которые переопределяют действие PHP по умолчанию, когда над объектом выполняются отдельные действия.

__get() __set()

/*
Перегрузка в PHP означает возможность динамически создавать свойства и методы. Эти динамические сущности обрабатываются с помощью магических методов, которые можно создать в классе для различных видов действий.

Методы перегрузки вызываются при взаимодействии со свойствами или методами, которые не были объявлены или не видны в текущей области видимости. Далее в этом разделе будут использоваться термины недоступные свойства или недоступные методы для обозначения этой комбинации объявления и области видимости.


Метод __set() будет выполнен при записи данных в недоступные (защищённые или приватные) или несуществующие свойства.

Метод __get() будет выполнен при чтении данных из недоступных (защищённых или приватных) или несуществующих свойств.
*/

namespace App;

protected float $amount;

class Invoice {
  public function __get(string $name){
  //что делать если запрашиваемого свойства нет
    if(property_exists($this, $name)){
      return $this->$name; //если свойство доступно вернем значение
    }
    return null;
  }
  
  public function __set(string $name, $value): void {
  //что делать при создании нового свойства которого нет
    if(property_exists($this, $name)){
      return $this->$name = $value; //если свойство доступно
    }
  }
}

$invoice = new \App\Invoice();

echo $invoice->amount; // если такого свойства нет получим null
                        // если есть то значение

$invoice->amount = 15; // присваивание значения даже для протектед или private 
                        // если есть __set()

__isset() __unset()

/*

Метод __isset() будет выполнен при использовании isset() или empty() на недоступных (защищённых или приватных) или несуществующих свойствах.

Метод __unset() будет выполнен при вызове unset() на недоступном (защищённом или приватном) или несуществующем свойстве.

*/

__call();

// запускается при вызове недоступных методов в контексте объект.

class MethodTest {
    public function __call($name, $arguments) {
        // Замечание: значение $name регистрозависимо.
        echo "Вызов метода '$name' "
             . implode(', ', $arguments). "\n";
    }

    public static function __callStatic($name, $arguments) {
        // Замечание: значение $name регистрозависимо.
        echo "Вызов статического метода '$name' "
             . implode(', ', $arguments). "\n";
    }
}

$obj = new MethodTest;
$obj->runTest('в контексте объекта');

MethodTest::runTest('в статическом контексте');

/*
результаты
Вызов метода 'runTest' в контексте объекта
Вызов статического метода 'runTest' в статическом контексте
*/

__toString()

class Invoice {
  public function __toString(): string{
    return 'класс как строка';
  }
}

$invoice = new Invoice();

echo $invoice; // класс как строка

__invoke()

//Метод __invoke() вызывается, когда скрипт пытается выполнить объект как функцию.
// на случай если у класса только одна задача

class CallableClass
{
    public function __invoke($x)
    {
        var_dump($x);
    }
}

$obj = new CallableClass();

$obj(5);
var_dump(is_callable($obj));

__debugInfo()

/*
Этот метод вызывается функцией var_dump(), когда необходимо вывести список свойств объекта. Если этот метод не определили, выводится каждое свойство объекта c модификаторами public, protected и private.
*/

class C
{
    private $prop;

    public function __construct($val)
    {
        $this->prop = $val;
    }

    public function __debugInfo()
    {
        return [
            'propSquared' => $this->prop ** 2,
        ];
    }
}

var_dump(new C(42));