概要
オブジェクト指向プログラミングでは、PHP はプログラミングに非常に便利な一連のマジック メソッドを提供します。 PHP のマジック メソッドは通常、__ (2 つのアンダースコア) で始まり、明示的な呼び出しを必要としませんが、特定の条件によってトリガーされます。この記事では、PHP で利用できるマジック メソッドを簡単にまとめます。
始める前に
PHP のマジック メソッドを要約する前に、後の例で使用する 2 つのクラスを定義しましょう:
コードをコピーします コードは次のとおりです:
クラスデバイス{
公開 $name
パブリック $バッテリー
パブリック $data = array();
パブリック $接続
保護された関数 connect() {
$this->connection = 'リソース';
echo $this->name . PHP_EOL;
}
保護された関数切断() {
$this->connection = null;
echo $this->name . PHP_EOL;
}
}
クラスバッテリー{
プライベート $charge = 0;
パブリック関数 setCharge($charge) {
$charge = (int)$charge;
if($charge
$charge = 0;
}
elseif($charge > 100) {
$charge = 100;
}
$this->charge = $charge;
}
}
?>
Device クラスには 4 つのメンバー プロパティと 2 つのメンバー メソッドがあります。 Battery クラスには 1 つのメンバー プロパティと 1 つのメンバー メソッドがあります。
コンストラクターとデストラクター
コンストラクターとデストラクターは、それぞれオブジェクトの作成時と破棄時に呼び出されます。オブジェクトが「破棄される」とは、オブジェクトへの参照が存在しないことを意味します。たとえば、オブジェクトを参照する変数が削除 (設定解除) されたり、再割り当てされたり、スクリプトの実行が終了したりすると、デストラクターが呼び出されます。
__construct()
__construct()コンストラクターは、最も一般的に使用される関数です。オブジェクトを作成するときに、コンストラクターで初期化作業を行うことができます。インスタンス化時に対応する数のパラメーターが渡される限り、コンストラクターには任意の数のパラメーターを定義できます。コンストラクターで例外が発生すると、オブジェクトの作成が妨げられます。
コードをコピーします コードは次のとおりです:
クラスデバイス{
パブリック関数 __construct(Battery $battery, $name) {
$this->バッテリー = $バッテリー;
$this->name = $name;
$this->connect();
}
}
コードをコピーします コードは次のとおりです:
コンストラクターをプライベート メソッドとして宣言すると、シンプレックス パターンでよく使用されるクラス外でオブジェクトが作成されるのを防ぎます。
__destruct()
デストラクターは通常、オブジェクトが破棄されるときに呼び出されます。デストラクターはパラメーターを受け取りません。データベース接続を閉じるなど、一部のクリーンアップ作業はデストラクターで実行されることがよくあります。
プロパティのオーバーロード
注意すべき点の 1 つは、PHP での「オーバーロード」は、他のほとんどの言語でのオーバーロードとは同じではありません。ただし、それらはすべて同じ関数を実装しています。
プロパティのオーバーロードに関与する 2 つのマジック メソッドは主にプロパティ アクセスを処理するために使用され、存在しない (またはアクセスできない) プロパティにアクセスしようとしたときに何が起こるかを定義します。
__get()
存在しないプロパティにアクセスしようとすると、魔法のメソッド __get() が呼び出されます。アクセスされた属性の名前を表すパラメーターを受け取り、属性の値を返します。上記の Device クラスには、次のコードに示すように、ここで役割を果たす data 属性があります。
コードをコピーします コードは次のとおりです:
クラスデバイス{
パブリック関数 __get($name) {
If(array_key_exists($name, $this->data)) {
return $this->data[$name];
}
null を返す;
}
}
コードをコピーします コードは次のとおりです:
クラスバッテリー{
プライベート $charge = 0;
パブリック関数 __get($name) {
If(isset($this->$name)) {
return $this->$name;
}
null を返す;
}
}
__set()
__set() マジック メソッドは、アクセスできないプロパティを変更しようとすると呼び出され、プロパティの名前を表すパラメータとプロパティの値を表すパラメータの 2 つを受け取ります。サンプルコードは次のとおりです:
コードをコピーします コードは次のとおりです:
クラスデバイス{
パブリック関数 __set($name, $value) {
// プロパティ名を配列キーとして使用します
$this->data[$name] = $value;
}
}
__isset()
__isset() マジック メソッドは、アクセスできないプロパティに対して isset() メソッドが呼び出されたときに呼び出され、プロパティの名前を表すパラメーターを受け取ります。プロパティが存在するかどうかを示すブール値を返す必要があります。コードは次のとおりです:
コードをコピーします コードは次のとおりです:
クラスデバイス{
パブリック関数 __isset($name) {
return array_key_exists($name, $this->data);
}
}
__unset()
__unset() マジックメソッドは、アクセスできない属性を破棄するために unset() 関数を呼び出すときに呼び出され、属性の名前を表すパラメーターを受け取ります。
オブジェクトを文字列に変換します
場合によっては、オブジェクトを文字列の形式で表現する必要があります。オブジェクトを直接出力すると、プログラムはエラー メッセージを出力します: PHP キャッチ可能な致命的なエラー: クラス Device のオブジェクトを文字列に変換できませんでした
__toString()
__toString() は、オブジェクトを文字列として使用するときに呼び出されます。パラメータは受け取りません。このメソッドを使用すると、オブジェクトの表現を定義できます。コードは次のとおりです:
コードをコピーします コードは次のとおりです:
クラスデバイス{
パブリック関数 __toString() {
$connected = (isset($this->connection)) '接続済み' : '切断済み';
$count = count($this->data);
$this->name . ' は ' . $count 個のメモリ内にあります' 。
}
...
}
静的マジック メソッド __set_state()。このメソッドは、var_export() 関数を使用してオブジェクトを出力するときに呼び出されます。 var_export() 関数は、PHP 変数を PHP コードに変換するために使用され、オブジェクトの属性値をパラメータとして含む連想配列を受け取ります。サンプルコードは次のとおりです:
コードをコピーします コードは次のとおりです:
クラスバッテリー{
//...
パブリック静的関数 __set_state(array $array) {
$obj = 新しい自分();
$obj->setCharge($array['charge']);
戻り $obj;
}
//...
}
デフォルトでは、オブジェクトは参照によって渡されます。したがって、オブジェクトを別の変数に割り当てるときは、オブジェクトへの参照が作成されるだけであり、オブジェクトはコピーされません。実際にオブジェクトをコピーするには、clone キーワードを使用する必要があります。 __クローン() __clone() マジックメソッド __clone() は上記の問題を解決できます。このマジック メソッドは、オブジェクトに対して clone キーワードが使用されるときに呼び出されます。この魔法のメソッドでは、任意のサブオブジェクトをクローンできます。コードは次のとおりです。
オブジェクトのシリアル化
__睡眠()
注意すべき点は、実行中のオブジェクトに影響を与える可能性があるため、この関数では破棄操作を実行しないでください。
__ウェイクアップ()
メソッドのオーバーロード
__call()
サンプルコードは次のとおりです: __callStatic() マジック メソッド __callStatic() には __call() と同じ機能があります。唯一の違いは、このメソッドが存在しない、またはアクセスできない静的メソッドにアクセスしようとしたときに呼び出されることです。サンプルコードは次のとおりです: 関数としてのオブジェクト オブジェクトを関数として使用する必要がある場合があります。オブジェクトを関数として使用することは、他の通常の関数を使用することと同じであり、パラメーターを渡すことができます。 __invoke()(PHP 5.3) オブジェクトを関数として使用しようとすると、マジックメソッド __invoke() が呼び出されます。このメソッドで定義されたパラメータはすべて、関数のパラメータとして使用されます。サンプルコードは次のとおりです: その他:__autoload() __autoload() メソッドは魔法のメソッドではありませんが、このメソッドは非常に便利です。ただし、PHP バージョンの更新により、この関数は推奨されなくなり、spl_auto_register() 関数に置き換えられました。
この「参照渡し」戦略は、オブジェクト内に含まれるオブジェクトにも適用されます。オブジェクトを複製しても、そのオブジェクト内のオブジェクトは複製されないため、最終的には両方のオブジェクトが同じ内部オブジェクトを共有することになります。サンプルコードは次のとおりです:
コードをコピーします コードは次のとおりです:
$device = 新しいデバイス(新しいバッテリー(), 'iMagic');
$device2 = $device のクローンを作成します;
$device->battery->setCharge(65);
echo $device2->battery->charge;
// 65
コードをコピーします コードは次のとおりです:
クラスデバイス{
...
パブリック関数 __clone() {
// Battery オブジェクトをコピーします
$this->battery = クローン $this->battery;
}
...
}
コードをコピーします コードは次のとおりです:
クラスデバイス{
公開 $name
パブリック $バッテリー
パブリック $data = array();
パブリック $接続
//...
パブリック関数 __sleep() {
戻り配列('名前', 'バッテリー', 'データ');
}
//...
}
コードをコピーします コードは次のとおりです:
クラスデバイス{
//...
パブリック関数 __wakeup() {
// ネットワークに再接続します
$this->connect();
}
//...
}
コードをコピーします コードは次のとおりです:
クラスデバイス{
//...
パブリック関数 __call($name, $arguments) {
// 子オブジェクトにこのメソッドがあることを確認してください
If(method_exists($this->connection, $name)) {
// 呼び出しを子オブジェクトに転送します
return call_user_func_array(array($this->connection, $name), $arguments);
}
null を返す;
}
//...
}
コードをコピーします コードは次のとおりです:
クラスデバイス{
//...
パブリック静的関数 __callStatic($name, $arguments) {
// クラスにこのメソッドがあることを確認してください
If(method_exists('接続', $name)) {
// 静的呼び出しをクラスに転送します
return call_user_func_array(array('Connection', $name), $arguments);
}
null を返す;
}
//...
}
コードをコピーします コードは次のとおりです:
クラスデバイス{
//...
パブリック関数 __invoke($data) {
echo $data;
}
//...
}
$device = 新しいデバイス(新しいバッテリー(), 'iMagic');
$device('テスト');
// $device->__invoke('test') と同等
// 出力: テスト