はじめに
PHP8 上級試験の問題集を解いていて「__call()」「__callStatic()」「mixed 型」が出てきました。
一見とっつきにくいですが、実は仕組みをイメージできれば理解しやすいポイントです。
この記事では、サンプルコードの実行結果とあわせて、身近な例え(電話交換手)で解説していきます。
目次
__call() と __callStatic() の基本
__call()
… 存在しない インスタンスメソッド が呼ばれたときに実行される__callStatic()
… 存在しない staticメソッド が呼ばれたときに実行される
つまり「呼び出しがあったけど、実際のメソッドが存在しない」ときの 代行処理 ができるマジックメソッドです。
サンプルコード
<?php
declare(strict_types=1);
error_reporting(-1);
class Hoge{
public function __call(string $name, array $arguments): mixed {
var_dump(__METHOD__, $name, $arguments);
return null;
}
public static function __callStatic(string $name, array $arguments): mixed {
var_dump(__METHOD__, $name, $arguments);
return null;
}
}
$obj = new Hoge();
$obj->test(1, "2nd"); // 存在しないインスタンスメソッド
Hoge::staticTest("1st", 1.4142); // 存在しないstaticメソッド
実行結果
string(12) "Hoge::__call"
string(4) "test"
array(2) {
[0]=>
int(1)
[1]=>
string(3) "2nd"
}
string(18) "Hoge::__callStatic"
string(10) "staticTest"
array(2) {
[0]=>
string(3) "1st"
[1]=>
float(1.4142)
}
このように、存在しないメソッド呼び出しが、それぞれ __call / __callStatic に振り分けられています。
図解イメージ(電話交換手の比喩)
$obj->test(1, "2nd");
│
▼
+--------------------+
| Hogeクラス社員名簿 |
+--------------------+
| foo() bar() |
| baz() |
+--------------------+
│
│ test() は存在しない!
▼
+--------------------+
| 電話交換手(__call) |
+--------------------+
| 「testは不在です。 |
| 引数[1,"2nd"]を |
| 代わりに預かります」|
+--------------------+
Hoge::staticTest("1st", 1.4142);
│
▼
+--------------------+
| Hogeクラス社員名簿 |
+--------------------+
| foo() bar() |
| baz() |
+--------------------+
│
│ staticTest() は存在しない!
▼
+-----------------------------+
| 代表電話交換手(__callStatic) |
+-----------------------------+
| 「staticTestは不在です。 |
| 引数["1st",1.4142]を |
| 代わりに預かります」 |
+-----------------------------+
mixed 型の補足
PHP8 から導入された mixed
型は「何でも返せる」ことを意味します。
int
を返してもOKstring
を返してもOKnull
を返してもOK- 他の型(array, object など)もすべてOK
イメージ図:
交換手の返答は自由
「intで返します」 → 42
「stringで返します」 → "OK"
「nullで返します」 → null
→ だから戻り値の型は mixed
今回のコードでは return null;
を書いていますが、他の型を返してもエラーにはなりません。
まとめ
__call
→ 存在しない インスタンスメソッド の代行処理__callStatic
→ 存在しない staticメソッド の代行処理mixed
→ 戻り値の型を縛らない柔軟な型指定
試験対策的には「__call / __callStatic の違い」と「mixed の意味」を押さえておくことが重要です。
実務的には、APIラッパーやプロキシ実装など、動的にメソッドを扱うシーンで役立ちます。