[PHP] マジックメソッド - 未定義属性の処理
マジックメソッドとは、クラスに定義されるメソッドで、あらかじめ役割が決められたいくつかのメソッドのことを言います。
以下の記事で取り上げたコンストラクタとデストラクタについても、マジックメソッドの一種です。
https://www.s-watanabe.work/2022/12/php_11.html
ここでは、未定義の属性への操作しようとしたときに呼び出されるメソッドについてまとめていきます。
__setメソッドと__getメソッド
PHPは基本的に未定義の属性へのアクセスが可能になっています。例えば以下のコードはエラーにならずに実行可能です。
class Test {
}
$test = new Test();
$test->name = 'Hoge';
echo "name=", $test->name, "\n\n";
var_dump($test);
実行結果は以下のようになります。
$ php test_magic-method.php name=Hoge object(Test)#1 (1) { ["name"]=> string(4) "Hoge" }
この属性をセットする時の処理を制御するのが __setメソッド、属性を取得する処理を制御するのが __getメソッドです。
マジックメソッドのシグネチャ
__setメソッド
アクセス修飾子 | public or なし |
---|---|
メソッド名 | __set |
第一引数 | string (属性名) |
第二引数 | mixed (値) |
戻り値 | void |
__getメソッド
アクセス修飾子 | public or なし |
---|---|
メソッド名 | __get |
第一引数 | string (属性名) |
戻り値 | mixed |
[実装例]__setメソッドと__getメソッド
コード
以下のコードは、__setメソッドで任意の属性を保存、__getメソッドで取り出す例です。__getメソッドで未定義だった場合は、例外を発生させています。
class Test {
private array $values = [];
public function __set($key, $value) {
$this->values[$key] = $value;
}
public function __get($key) {
return $this->values[$key] ??
throw new Exception("Undefined property[{$key}]");
}
}
$test = new Test();
$test->name = "Hoge";
echo "name=", $test->name, "\n\n";
var_dump($test);
実行結果
$ php test_magic-method.php name=Hoge object(Test)#1 (1) { ["values":"Test":private]=> array(1) { ["name"]=> string(4) "Hoge" } }
__issetメソッドと__unsetメソッド
__issetメソッドと__unsetメソッドは、それぞれ未定義の属性にisset関数、unset関数を実行したときに呼び出されるメソッドです。
マジックメソッドのシグネチャ
__issetメソッド
アクセス修飾子 | public or なし |
---|---|
メソッド名 | __isset |
第一引数 | string (属性名) |
戻り値 | bool |
__unsetメソッド
アクセス修飾子 | public or なし |
---|---|
メソッド名 | __unset |
第一引数 | string (属性名) |
戻り値 | void |
[実装例]__issetメソッドと__unsetメソッド
コード
以下のコードは、__setメソッドと__getメソッドの例で使用したコードに、__issetメソッドと__unsetメソッドを加えました。このように__isset、__unsetは基本的に__set、__getメソッドとセットで使います。
class Test {
private array $values = [];
public function __set($key, $value) : void {
$this->values[$key] = $value;
}
public function __get($key) {
return $this->values[$key] ??
throw new Exception("Undefined property[{$key}]");
}
public function __isset(string $key) : bool {
echo __METHOD__, "\n";
return isset($this->values[$key]);
}
public function __unset(string $key) : void {
echo __METHOD__, "\n";
unset($this->values[$key]);
}
}
$test = new Test();
$test->var = 1;
$a = isset($test->var);
echo "isset=", $a, "\n\n";
unset($test->var);
echo "unset\n\n";
$b = isset($test->var);
echo "isset=", $b, "\n\n";
var_dump($test);
実行結果
実行結果を確認すると、isset関数とunset関数に対応したメソッドがそれぞれのタイミングで呼び出されていることが分かります。
$ php test_magic-method.php Test::__isset isset=1 Test::__unset unset Test::__isset isset= object(Test)#1 (1) { ["values":"Test":private]=> array(0) { } }
__callメソッドと__callStaticメソッド
__callメソッドと__callStaticメソッドは未定義のメソッドを実行したときに呼び出されるマジックメソッドです。属性の操作とは直接関係ありませんが、__getメソッド・__setメソッドとよく似た動作をするのでこちらでまとめておきます。
マジックメソッドのシグネチャ
__callメソッド
アクセス修飾子 | public or なし |
---|---|
メソッド名 | __call |
第一引数 | string (メソッド名) |
第二引数 | array |
戻り値 | mixed |
__callStaticメソッド
アクセス修飾子 | public static or static |
---|---|
メソッド名 | __callStatic |
第一引数 | string (メソッド名) |
第二引数 | array |
戻り値 | mixed |
[実装例]__callメソッド呼び出し確認
コード
class Test {
public function __call(string $function, array $args) {
echo __METHOD__, "\n";
var_dump($function, $args);
}
}
$test = new Test();
$test->addVar(1);
実行結果
$ php test_magic-method.php Test::__call string(6) "addVar" array(1) { [0]=> int(1) }
[実装例]Getter、Setterを__callメソッドで実装する
__getメソッドと__setメソッドの実装例のコードは、__callメソッドを使って次のように置き換えることが出来ます。
コード
class Test {
private array $values = [];
public function __call(string $function, array $args) {
if (empty($args)) {
if (!array_key_exists($function, $this->values))
throw new Exception("Undefined property[{$function}]");
return $this->values[$function];
} else {
$this->values[$function] = $args[0];
}
}
}
$test = new Test();
$test->name("Hoge");
echo "name=", $test->name(), "\n\n";
var_dump($test);
実行結果
$ php test_magic-method.php name=Hoge object(Test)#1 (1) { ["values":"Test":private]=> array(1) { ["name"]=> string(4) "Hoge" } }
コメント
コメントを投稿