__get, __set, __isset, __unset
CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 46/91。
PHPは、プロパティへのアクセスをインターセプトする4つのマジックメソッドを提供しています:__get()、__set()、__isset()、および__unset()。これらは、存在しないプロパティやアクセスできないプロパティにアクセスしようとしたときにトリガーされます。
__get() メソッドは、アクセス不能なプロパティを読み取るときに呼び出されます。一方、__set() はプロパティへの書き込みを処理します。これにより、動的なプロパティを作成したり、プロパティがアクセスされたときにロジックを追加したりできます。
<?php
class DynamicObject {
private array $data = [];
public function __get(string $name): mixed {
return $this->data[$name] ?? null;
}
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
}
$obj = new DynamicObject();
$obj->title = "Hello";
$obj->count = 42;
echo $obj->title . " - " . $obj->count;
出力:
Hello - 42__isset() メソッドは isset() または empty() によってトリガーされ、__unset() は unset() 関数に対応します。
<?php
class DynamicObject {
private array $data = [];
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
public function __isset(string $name): bool {
return isset($this->data[$name]);
}
public function __unset(string $name): void {
unset($this->data[$name]);
}
}
$obj = new DynamicObject();
$obj->name = "Test";
echo isset($obj->name) ? "exists" : "missing";
出力:
existsこれらのメソッドは、柔軟なデータコンテナの作成、遅延読み込みの実装、あるいはオブジェクト指向の構造を維持しながら配列のように振る舞うオブジェクトの構築によく使用されます。
チャレンジ
簡単マジックメソッドを使用して設定を動的に保存する、柔軟な設定マネージャーを構築しましょう。作成するクラスは、プロパティへのアクセスをインターセプトして設定値を管理し、設定が存在するかどうかを確認し、必要に応じて削除します。これらすべてを、各プロパティを明示的に定義することなく行います。
コードは2つのファイルに分けて構成します:
Config.php— 設定値を内部的に保存するためのプライベート配列を使用するConfigクラスを作成します。以下の4つのプロパティマジックメソッドを実装してください:__get($name)— 指定されたキーの値を返します。キーが存在しない場合は"undefined"を返します。__set($name, $value)— 指定されたキーで値を保存します。__isset($name)— 設定内にキーが存在するかどうかを返します。__unset($name)— 設定からキーを削除します。
count()メソッドも追加してください。main.php— Configファイルをインクルードします。3つの入力(設定名、設定値、および2つ目の設定名)を受け取ります。Configインスタンスを作成し、以下の操作を実行してください:- 1つ目の設定に指定された値をセットする
isset()を使用して1つ目の設定が存在するかどうかを出力する —"exists"または"missing"と出力- 1つ目の設定の値を出力する
- 現在の設定数を出力する
unset()を使用して1つ目の設定を削除する- 1つ目の設定が現在存在するかどうかを出力する —
"exists"または"missing"と出力 - 2つ目の設定(一度もセットされていないもの)の値を出力する
各出力はそれぞれの行に分けてください。マジックメソッドを使用すると、実際のプロパティが定義されていなくても、$config->theme = "dark" や isset($config->theme) のような自然なプロパティ構文を使用して Config オブジェクトを操作できます。
チートシート
PHPは、プロパティへのアクセスをインターセプトするための4つのマジックメソッドを提供しています:
__get(string $name): mixed— アクセス不能なプロパティを読み取るときに呼び出されます__set(string $name, mixed $value): void— アクセス不能なプロパティに書き込むときに呼び出されます__isset(string $name): bool—isset()またはempty()によって実行されます__unset(string $name): void—unset()によって実行されます
__get() と __set() の例:
<?php
class DynamicObject {
private array $data = [];
public function __get(string $name): mixed {
return $this->data[$name] ?? null;
}
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
}
$obj = new DynamicObject();
$obj->title = "Hello";
echo $obj->title; // Hello
__isset() と __unset() の例:
<?php
class DynamicObject {
private array $data = [];
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
public function __isset(string $name): bool {
return isset($this->data[$name]);
}
public function __unset(string $name): void {
unset($this->data[$name]);
}
}
$obj = new DynamicObject();
$obj->name = "Test";
echo isset($obj->name) ? "exists" : "missing"; // exists
これらのメソッドは、オブジェクト指向の構造を維持しながら、動的なプロパティ、遅延読み込み(レイジーローディング)、および柔軟なデータコンテナを可能にします。
自分で試してみよう
<?php
require_once 'Config.php';
// 入力を読み込む
$settingName1 = trim(fgets(STDIN));
$settingValue = trim(fgets(STDIN));
$settingName2 = trim(fgets(STDIN));
// TODO: Config インスタンスを作成する
// TODO: 1つ目の設定に指定された値をセットする
// TODO: 1つ目の設定が存在するかどうかを出力する ("exists" または "missing")
// TODO: 1つ目の設定の値を出力する
// TODO: 現在の設定の数を出力する
// TODO: unset() を使用して1つ目の設定を削除する
// TODO: 1つ目の設定が現在存在するかどうかを出力する ("exists" または "missing")
// TODO: 2つ目の設定(一度もセットされていないもの)の値を出力する
?>このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
8マジックメソッド
マジックメソッド入門__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone とオブジェクトのクローン__serialize & __unserializeまとめ - カスタムコレクション