PHPのマジックメソッド一覧と使い方まとめ

php.netの一覧（ http://php.net/manual/ja/language.oop5.magic.php ）が見にくかったので自分なりにまとめておく。

- 2018/05/23 サンプルコードの見直し・追加
- 2020/02/21 サンプルコードをLaravelを意識したものに見直し


# 比較的使う子たち
- __construct
- __call
- __callStatic
- __get
- __set
- __toString

# __construct( $argments )
クラスがインスタンス化されたときに呼ばれる。
よくある初期化用。依存注入でも使用される。

```php
public function __construct( HogeService $hoge_service ) {
    $this->hoge_service = $hoge_service ;
}
```

```php
public function __construct( $name = '名無しさん' ) {
    $this->name = $name;
}
```

# __destruct( void )
インスタンスが削除されたときに呼ばれる。
コンストラクタでオープンしたファイルのクローズなどの終了処理を書いておくと便利。

```php
public function __destruct() {
    fclose($this->handle);
}
```

# __call( $name, $argments )
インスタンスに存在しない関数が呼ばれたとき実行される。

```php
public function __call($name, $argments) {
    $name = 'action_'.$name;
    return $name($argments);  //関数action_xxxを実行
}
```

# __callStatic( $name, $argments )
インスタンスに存在しない静的関数が呼ばれたとき実行される。

```php
public static function __callStatic( $name, $argments ) {
    $name = 'scope'.$name;
    static::$name($argments);      //関数scopexxxを実行
}
```

# __get($name)
インスタンスに存在しない変数プロパティが呼び出されたときに実行される。

```php
public static function __get( $name ) {
    return $this->attributes[$name];    //配列attributesのxxxを返す
}
```

# __set($name, $value)
インスタンスに存在しない変数プロパティに代入されたときに実行される。

```php
public static function __set( $name, $value ) {
    $this->attributes[$name] = $value;  //配列attributesのxxxに代入
}
```


# __isset($name)
インスタンスのアクセス不能プロパティに対して isset() あるいは empty() を実行したときに実行される。

```php
public function __isset($name) {
    return isset($this->attributes[$name]); //配列attributesのxxxが存在するかチェック
}
```


# __unset()
インスタンスのアクセス不能プロパティに対して unset() を実行したときに実行される。

```php
public function __unset($name) {
    unset($this->attributes[$name]);      //配列attributesのxxxを削除
}
```
# __sleep()
インスタンスをシリアライズ化時に呼ばれる。
シリアライズに不要なデータや、変換不能なもの（ファイルハンドルなど）を除外するときに使う。
データ授受目的ならjson化した方がいい気もする。
このメソッドではシリアライズ化する対象の変数名文字列の配列を返すようにする。

```php
class Hoge {
    public $file_name;
    private $file_handle;
    private $secret_data;
    
    public function __sleep() {
        return [
            'file_name',
        ];
    }
}
```

# __wakeup()
インスタンスをアンシリアライズ化時に呼ばれる。
アンシリアライズしたデータをからインスタンスに必要なデータを再構築するときに使う。

```php
class Hoge {
    public $file_name;
    private $file_handle;
    private $secret_data;
    
    public function __wakeup() {
        $this->file_handle = fopen($this->file_name, 'r');
    }
}
```


# __toString()
インスタンスがechoなどsting型が要求されえたとき呼ばれる。

```php
class User {
    public function __toString() {
        return "{$this->name} ({$this->age}歳)";
    }
}

$user = new User();
echo $user;
(string) $user;
```

# __invoke( $argments )
インスタンスが関数として呼ばれたときに実行される。

```php
public function __invoke() {
    var_dump($this->text);      //デバッグ用
}
```

# __set_state( array $properties )
インスタンスをvar_exportが呼ばれたときに実行される。

```php
public function __set_state( $properties ) {
    //$propertiesの加工など
    return $properties;
}
```

# __debugInfo()
インスタンスをvar_dumpが呼ばれたときに実行される。

```php
public function __debugInfo() {
    return ['data' => $this->data];
    //$返す値を指定
}
```

# __clone()
インスタンスをクローンするときに呼ばれる。
普通にクローンすると参照渡しになる値（datetimeなど）を別物としてクローンしたい場合時に使う。
最近はイミュータブルなものが増えてきているので表立って使うことは少ないかも。

```php
class A {
   public function __construct() {
      $this->datetime = new DateTime();
   }
}
$a = new A;
$a2 = clone $a;
$a->datetime->modify('tomorrow');
// $a2->datetimeと、$a->datetimeの参照先は同じであるため両方の値が変更されるように見える。
```

```php
class B extends A {
    public function __clone() {
        $this->datetime = clone $this->datetime;
    }
}
$b = new B;
$b2 = clone $b;
$b->datetime->modify('tomorrow');
// $b2->datetimeと、$b->datetimeの参照先は異なるため$b->datetimeのみ変更される。
```