1. ホーム 
  2. 備忘録 
  3. PHP

マジックメソッド

マジックメソッド一覧

説明コード記述
テストコード記述
関数 用途
__construct コンストラクタ
__destruct デストラクタ
__call アクセス不能メソッドをオブジェクトのコンテキストで実行したときに起動する
__callStatic アクセス不能メソッドを静的メソッドとして呼び出した場合に起動する
__get アクセス不能(protected または private)または存在しないプロパティからデータを読み込む際に使用される
__set アクセス不能(protected または private)または存在しないプロパティへデータを書き込む際に実行される
__isset isset() あるいは empty() をアクセス不能(protected または private)または存在しないプロパティに対して実行したときに起動する
__unset unset() をアクセス不能(protected または private)または存在しないプロパティに対して実行したときに起動する
__sleep オブジェクトをシリアライズ化した際に呼ばれる。
このメソッドでシリアライズしたい変数の変数名を配列として返すことで使用できる
親クラスの private プロパティの名前を返すことはできないのでその場合は __serialize を使用すること
__wakeup オブジェクトをアンシリアライズ化した際に呼ばれる。
シリアル化の際に失われたデータベース接続を再度確立したり、 その他の再初期化を行う
__serialize オブジェクトをシリアライズ化した際に呼ばれる。
__sleep と異なり、このメソッドでシリアライズしたいデータを"連想配列"の形で返すことで使用できる
キー名も任意で設定できるため、変数名と一致させなくてもよくなる
__unserialize オブジェクトをアンシリアライズ化した際に呼ばれる。
__sleep & __wakeup と異なり、__serialize & __unserialize では任意の連想配列形式にできる分、アンシリアライズ時に渡されたデータから元の変数の状態を復元しなくてはいけない
__toString クラスが文字列に変換される際の動作を決めることができる
__invoke スクリプトがオブジェクトを関数としてコールしようとした際にコールされる
__clone オブジェクトのクローンが作成されるときに起動する
各プロパティに対して何も記載がなければシャローコピーとなる

__construct

__construct(mixed ...$values = ""): void

クラスのコンストラクタを宣言することができる

$values に任意の引数を設定することでクラスの生成時に外部から変数を渡すことができる


__destruct

__destruct(): void

クラスのデストラクタを宣言することができる

特定のオブジェクトを参照するリファレンスがひとつもなくなったときにコールされる

ファイルのクローズ処理とか書くことが多いかも


__call

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

アクセス不能メソッドをオブジェクトのコンテキストで実行したときに起動する

$name には実行しようとした関数名が入る

$arguments には実行しようとした関数に渡したパラメータが入る


__callStatic

public static __callStatic(string $name, array $arguments): mixed

アクセス不能メソッドを静的メソッドとして呼び出した場合に起動する

$name には実行しようとした関数名が入る

$arguments には実行しようとした関数に渡したパラメータが入る


__get

public __get(string $name): mixed

アクセス不能(protected または private)または存在しないプロパティからデータを読み込む際に使用される

$name には操作しようとしたプロパティの名前が入る


__set

public __set(string $name, mixed $value): void

アクセス不能(protected または private)または存在しないプロパティへデータを書き込む際に実行される

$name には操作しようとしたプロパティの名前が入る

$value には $name に設定しようとした値が入る


__isset

public __isset(string $name): bool

isset() あるいは empty() をアクセス不能(protected または private)または存在しないプロパティに対して実行したときに起動する

$name には操作しようとしたプロパティの名前が入る


__unset

public __unset(string $name): void

unset() をアクセス不能(protected または private)または存在しないプロパティに対して実行したときに起動する

$name には操作しようとしたプロパティの名前が入る


__sleep

public __sleep(): array

オブジェクトをシリアライズ化した際に呼ばれる。

親クラスの private プロパティの名前を返すことはできないのでその場合は __serialize を使用すること

__sleep も __serialize もない状態で serialize() を呼んだ場合は見境なく全てシリアライズ化しようとするので、シリアライズ化不要なデータがある場合はどちらかを使用する

class Sample
{
  protected $connection; // コネクションなどは使用するタイミングで繋ぐものなのでシリアライズ化はいらない
  private $username, $password; // この2つをシリアライズ化しておけばよい
  
  public function __sleep()
  {
    return array('username', 'password');
  }
}

上記のようにクラス内のシリアライズ化したい変数の変数名を __sleep メソッド内で返すようにする


__wakeup

public __wakeup(): void

オブジェクトをアンシリアライズ化した際に呼ばれる。

下記のようにコネクションを繋ぎなおしたい場合や、変数展開した上で初期化処理を通したい場合などに使用する

class Sample
{
  protected $connection; // アンシリアライズ時に復元したい
  private $username, $password; // シリアライズ時に残っている情報

  public function __sleep()
  {
    return array('username', 'password');
  }

  public function __wakeup()
  {
    // username と password は変数展開されるが、connection は新たに繋ぎなおす必要がある
    $this->connect();
  }

  private function connect()
  {
    $this->connection = new Connection($this->username, $this->password);
  }
}

__serialize

public __serialize(): array

オブジェクトをシリアライズ化した際に呼ばれる

__sleep とは異なり、連想配列形式でシリアライズ時のデータを設定できる

__sleep と __serialize の両方が定義されていた場合は __serialize のほうが優先される

PHP 7.4.0 以降から使用可能


__unserialize

public __unserialize(array $data): void

オブジェクトをアンシリアライズ化した際に呼ばれる

__wakeup と __unserialize の両方が定義されていた場合は __unserialize のほうが優先される

__wakeup では unserialize() に渡されたデータの中で同じ変数名のものがあれば自動で展開されていたが、__unserialize の場合は全て自分で展開しなければいけない

PHP 7.4.0 以降から使用可能


__toString

public __toString(): string

クラスが文字列に変換される際の動作を決めることができる

PHP 8.0.0 以降では __toString を含む全てのクラスは暗黙のうちに Stringable インターフェースを実装するようになったが、明示的に実装しておくほうがよいので忘れずにつけておくこと


__invoke

__invoke( ...$values): mixed

スクリプトがオブジェクトを関数としてコールしようとした際にコールされる

公式ドキュメントにあったソートの使用例が参考になったので貼っておく

class Sort
{
    private $key;

    /**
     * コンストラクタ
     *
     * @param string $key ソートに使用するキー名
     */
    public function __construct(string $key)
    {
        $this->key = $key;
    }

    /**
     * ソート処理で使用するメソッド
     *
     * @param array $a 比較対象a
     * @param array $b 比較対象b
     * @return integer 結果
     */
    public function __invoke(array $a, array $b): int
    {
        return $a[$this->key] <=> $b[$this->key];
    }
}

// データ例
$customers = [
    ['id' => 1, 'first_name' => 'John', 'last_name' => 'Do'],
    ['id' => 3, 'first_name' => 'Alice', 'last_name' => 'Gustav'],
    ['id' => 2, 'first_name' => 'Bob', 'last_name' => 'Filipe']
];

//================================================================================//
// 本来 usort の第2引数は『callback(mixed $a, mixed $b): int 』を渡さないといけないが、
// Sort クラスの __invoke に上記の条件に沿った関数を設定することで実現している
//================================================================================//

// $customers を 'first_name' でソートします
usort($customers, new Sort('first_name'));
print_r($customers);

// $customers を 'last_name' でソートします
usort($customers, new Sort('last_name'));
print_r($customers);

__clone

__clone(): void

オブジェクトのクローンが作成されるときに起動する

各プロパティに対して何も記載がなければシャローコピーとなる

class SubObject
{
  public $value;
}

class MainObject
{
  public $sub1;
  public $sub2;

  public function __construct()
  {
    $this->sub1 = new SubObject();
    $this->sub2 = new SubObject();
  }

  public function __clone()
  {
    $this->sub1 = clone $this->sub1;
  }
}

$main = new MainObject();
$main->sub1->value = 1;
$main->sub2->value = 2;

// クローンを作成する(ディープコピーしたい)
$clone = clone $main;

// メイン側だけ書き換える
$main->sub1->value = 3;
$main->sub2->value = 4;

// MainObject クラスの __clone メソッドでディープコピーしていない sub2 はメイン側と一緒に書き変わってしまう
echo $clone->sub1->value; // 1 OK
echo $clone->sub2->value; // 4 NG

    参考文献

  1. 公式ドキュメント