マジックメソッド

マジックメソッドは、 ある動作がオブジェクトに対して行われた場合に、 PHP のデフォルトの動作を上書きする特別なメソッドです。
__で始まる全てのメソッドは、 PHP によって予約されています。 よって、PHP の動作を上書きするのでなければ、 このようなメソッド名を使うことは推奨されません。
__construct(), __destruct(), __clone() を除く全てのマジックメソッドは、 public として宣言しなければいけません。 そうしないと、 E_WARNING レベルの警告が発生します。
__callStatic以外、静的呼び出しには対応しない
マジックメソッドの定義で型宣言が使われている場合、 それらは、このマニュアルで説明しているシグネチャと同じでなければいけません。
それぞれのメソッドで戻り値は決まっている。
プロパティのオーバーロードはオブジェクトのコンテキストでのみ動作します。 これらのマジックメソッドは、static メソッドとしては呼び出されません。 したがって、これらのメソッドを static メソッドとして宣言してはいけません。 マジックメソッドを static メソッドとして宣言すると警告が発生します。

主なマジックメソッド

メソッド呼び出しのタイミング戻り値
__get未定義のプロパティを取得しようとしたときmixed
__set未定義のプロパティを設定しようとしたときvoid
__isset未定義のプロパティをisset関数で処理しようとしたときbool
__unset未定義のプロパティをunset関数で処理しようとしたときvoid
__call未定義のインスタンスメソッドをコールしたときmixed
__callStatic未定義の静的メソッドをコールしたときmixed
__toStringprint命令などでオブジェクトの文字列表現を要求されたときstring
__invokeオブジェクトが関数の形式で呼び出されたときmixed
__cloneclone命令でオブジェクトを複製したときvoid
__debuginfovar_dump命令でオブジェクトをダンプしようとしたときarray
__construct新たにオブジェクトが 生成される度にこのメソッドをコールします。
子クラスでオーバライドしても、 シグネチャの互換性に関するルール(注1)は適用されません。
void
__destruct特定のオブジェクトを参照するリファレンスがひとつもなくなったときにコールされます。 あるいは、スクリプトの終了時にも順不同でコールされます。void
(注1)シグネチャの互換性に関するルール

メソッドをオーバーライドするときは、 子クラスのシグネチャが親クラスのそれと互換性がなければいけません。 互換性が壊れた場合、致命的なエラーが発生します。 PHP 8.0.0 より前のバージョンでは、 互換性が壊れた場合に、E_WARNING レベルの警告が発生していました。
但し、コンストラクタ と private メソッドについては、 この規則の例外で、 オーバライドしたシグネチャにミスマッチがあっても致命的なエラーにはなりません。

__set でメソッドを追加する

bindToメソッド
public Closure::bindTo(?object $newThis, object|string|null $newScope = “static”): ?Closure

class Person {
  public string $firstName;
  public string $lastName;
  private array $methods = [];

  public function __set(string $name, Closure $method) : void {
    $this->methods[$name] = $method->bindTo($this, self::class);
  }

  public function __call(string $name, array $args) : mixed {
    if (!array_key_exists($name, $this->methods)) {
      throw new Exception("${name} method is not existed.");
    }
    return $this->methods[$name](...$args);
  }
}

$p = new Person();
$p->lastName = '東京';
$p->firstName = '太郎';
$p->bye = function(): void { //無名関数を登録する(Closure)
  print "{$this->lastName}{$this->firstName}さん";
};
$p->bye();

public __call(string $name, array $arguments): mixed

未定義のインスタンスメソッドをコールしたとき。
引数 $arguments は配列で、メソッド $name に渡そうとしたパラメータが格納されます。

__clone(): void

オブジェクトのクローンが作成される際、PHP は、そのオブジェクトのプロパティを 全てシャローコピーします。他の変数へのリファレンスを保持する全てのプロパティは、 リファレンスのままとなります。ディープコピーしたい場合は、foreach命令で複製を生成する。

public function __clone():void {
	foreach($this->list as &$value) {
		$value = clone $value;
	}
}