この記事では、PHPの一般的なマジックメソッドの機能と使用例を中心に紹介します。この記事では、コンストラクターとデストラクターの__construct()と__desctruct()、およびプロパティのオーバーロード(Property Overloading)について説明します。 ) __get()、__set()、__isset() などの魔法のメソッドを必要とする友人は参照できます
。概要
オブジェクト指向プログラミングでは、PHP はプログラミングに非常に便利な一連のマジック メソッドを提供します。 PHP のマジック メソッドは通常、__ (2 つのアンダースコア) で始まり、明示的な呼び出しを必要としませんが、特定の条件によってトリガーされます。この記事では、PHP で利用できるマジック メソッドを簡単にまとめます。
始める前に
PHP のマジック メソッドを要約する前に、後の例で使用する 2 つのクラスを定義しましょう:
コードは以下の通りです:
クラスデバイス{
public $name;
パブリック $battery;
public $data = array();
パブリック $connection;
保護された関数 connect() {
$this->connection = 'リソース';
echo $this->name . PHP_EOL;
}
保護された関数disconnect() {
$this->connection = null;
echo $this->name ' 切断されました' 。
}}
クラスバッテリー{
プライベート $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() コンストラクターは、最も一般的に使用される関数です。オブジェクトを作成するときに、コンストラクターで初期化作業を行うことができます。インスタンス化時に対応する数のパラメーターが渡される限り、コンストラクターには任意の数のパラメーターを定義できます。コンストラクターで例外が発生すると、オブジェクトの作成が妨げられます。
コードは次のとおりです:
クラスデバイス{
public function __construct(Battery $battery, $name) {
$this->battery = $battery;
$this->name = $name;
$this->connect();
}
}
上記のサンプルコードでは、Deviceクラスのコンストラクターがメンバーのプロパティに値を代入し、connect()メソッドを呼び出しています。
コードは次のとおりです:
コンストラクターをプライベートメソッドとして宣言すると、シンプレックスパターンでよく使用されるクラス外でオブジェクトが作成されるのを防ぐことができます。
__destruct()
デストラクタは通常、オブジェクトが破棄されるときに呼び出されます。デストラクタはパラメータを受け取りません。データベース接続を閉じるなど、一部のクリーンアップ作業はデストラクターで実行されることがよくあります。
プロパティのオーバーロード
注意すべき点の 1 つは、PHP での「オーバーロード」は、他のほとんどの言語でのオーバーロードとは同じではありません。ただし、それらはすべて同じ関数を実装しています。
プロパティのオーバーロードに関与する 2 つのマジック メソッドは、主にプロパティ アクセスを処理するために使用され、存在しない (またはアクセスできない) プロパティにアクセスしようとしたときに何が起こるかを定義します。
__get()
存在しないプロパティにアクセスしようとすると、魔法のメソッド__get()が呼び出されます。アクセスされた属性の名前を表すパラメーターを受け取り、属性の値を返します。上記の Device クラスには、次のコードに示すように、ここで役割を果たす data 属性があります。
コードは次のとおりです:
クラスデバイス{
パブリック関数 __get($name) {
if(array_key_exists($name, $this->data)) {
return $this->data[$name];
}
null を返す;
}
}
このマジック メソッドの最も一般的な使用法は、「読み取り専用」属性を作成してアクセス制御を拡張することです。上記の Battery クラスには、プライベート属性 $charge があります。__get() マジック メソッドを使用してこの属性を拡張し、クラス外では読み取り可能ですが変更できないようにすることができます。コードは次のとおりです:
コードは以下の通りです:
クラスバッテリー{
プライベート $charge = 0;
パブリック関数 __get($name) {
if(isset($this->$name)) {
$this->$name;を返す
}
null を返す;
}
}
__set()
アクセスできないプロパティを変更しようとすると、__set() マジック メソッドが呼び出されます。このメソッドは 2 つのパラメータを受け取ります。1 つはプロパティの名前を表し、もう 1 つはプロパティの値を表します。サンプルコードは次のとおりです:
コードは以下の通りです:
クラスデバイス{
パブリック関数 __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()(PHP 5.1)
静的マジックメソッド__set_state()、このメソッドはvar_export()関数を使ってオブジェクトを出力するときに呼び出されます。 var_export() 関数は、PHP 変数を PHP コードに変換するために使用され、オブジェクトの属性値をパラメータとして含む連想配列を受け取ります。サンプルコードは次のとおりです:
コードは以下の通りです:
クラスバッテリー{
//...
パブリック静的関数 __set_state(array $array) {
$obj = 新しい自分();
$obj->setCharge($array['charge']);
$objを返す;
}
//...
}
クローンオブジェクト
デフォルトでは、オブジェクトは参照によって渡されます。したがって、オブジェクトを別の変数に割り当てるときは、オブジェクトへの参照が作成されるだけであり、オブジェクトはコピーされません。実際にオブジェクトをコピーするには、clone キーワードを使用する必要があります。
この「参照渡し」戦略は、オブジェクト内に含まれるオブジェクトにも適用されます。オブジェクトを複製しても、そのオブジェクト内のオブジェクトは複製されないため、最終的には両方のオブジェクトが同じ内部オブジェクトを共有することになります。サンプルコードは次のとおりです:
コードは以下の通りです:
$device = new Device(new Battery(), 'iMagic');
$device2 = クローン $device;
$device->battery->setCharge(65);
echo $device2->battery->charge;
// 65
__clone()
__clone() マジックメソッド __clone() で上記の問題を解決できます。このマジック メソッドは、オブジェクトに対して clone キーワードが使用されるときに呼び出されます。この魔法のメソッドでは、任意のサブオブジェクトをクローンできます。コードは次のとおりです。
コードは以下の通りです:
クラスデバイス{
…
パブリック関数 __clone() {
// Battery オブジェクトをコピーします
$this->battery = クローン $this->battery;
}
…
}
オブジェクトのシリアル化
シリアル化とは、任意のデータを文字列形式に変換するプロセスです。シリアル化は通常、オブジェクト全体をデータベースに保存するか、ファイルに書き込むために使用されます。保存されたデータを逆シリアル化する場合、シリアル化する前にオブジェクトを取得できます。ただし、データベース接続など、すべてのデータをシリアル化できるわけではありません。幸いなことに、この問題を解決するための魔法のトリックがあります。
__sleep()
オブジェクトをシリアル化するとき(serialize()を呼び出すとき)、マジックメソッド__sleep()が呼び出されます。パラメーターは取らず、シリアル化する必要があるすべてのプロパティを含む配列を返す必要があります。このマジック メソッド内では、他の操作も実行できます。
注意すべき点は、実行中のオブジェクトに影響を与える可能性があるため、この関数では構造化操作を実行しないでください。
サンプルコードは以下の通りです:
コードは以下の通りです:
クラスデバイス{
public $name;
パブリック $battery;
public $data = array();
パブリック $connection;
//...
パブリック関数 __sleep() {
配列を返す('名前', 'バッテリー', 'データ');
}
//...
}
__wakeup()
格納されたオブジェクトを逆シリアル化するときに、マジックメソッド __wakeup() が呼び出されます。パラメータを受け取らず、値も返しません。これを使用して、シリアル化中に失われたデータベース接続またはリソースを処理できます。コードは次のとおりです:
コードは以下の通りです:
クラスデバイス{
//...
パブリック関数 __wakeup() {
// ネットワークに再接続します
$this->connect();
}
//...
}
メソッドのオーバーロード
PHP には、メンバーメソッドに関連する 2 つのマジック メソッド __call() と __callStatic() もあります。これら 2 つのマジック メソッドは、属性のオーバーロード メソッドに似ています。
__call()
存在しない、またはアクセスできないメソッドを呼び出す場合、マジックメソッド__call()が呼び出されます。これは 2 つのパラメータを受け取ります。1 つは呼び出されるメソッドの名前で、もう 1 つは関数パラメータを含む配列です。このメソッドを使用して、子オブジェクト内の同じ名前の関数を呼び出すことができます。
この例では、名前付き関数を動的に呼び出すことができる関数 call_user_func_array() に注目してください。
サンプルコードは以下の通りです:
コードは以下の通りです:
クラスデバイス{
//...
パブリック関数 __call($name, $arguments) {
// 子オブジェクトにこのメソッドがあることを確認してください
if(method_exists($this->connection, $name)) {
// 呼び出しを子オブジェクトに転送します
return call_user_func_array(array($this->connection, $name), $arguments);
}
null を返す;
}
//...
}
__callStatic()
マジックメソッド __callStatic() は __call() と同じ機能を持っていますが、唯一の違いは、このメソッドが存在しない、またはアクセスできない静的メソッドにアクセスしようとしたときに呼び出されることです。サンプルコードは次のとおりです:
コードをコピーします。コードは次のとおりです:
クラスデバイス{
//...
パブリック静的関数 __callStatic($name, $arguments) {
// 私たちのクラスにこのメソッドがあることを確認してください
if(method_exists('Connection', $name)) {
// 静的呼び出しをクラスに転送します
return call_user_func_array(array('Connection', $name), $arguments);
}
null を返す;
}
//...
}
関数としてのオブジェクト
オブジェクトを関数として使用する必要がある場合があります。オブジェクトを関数として使用することは、他の通常の関数を使用することと同じであり、パラメーターを渡すことができます。
__invoke()(PHP 5.3)
オブジェクトを関数として使用しようとすると、魔法のメソッド __invoke() が呼び出されます。このメソッドで定義されたパラメータはすべて、関数のパラメータとして使用されます。サンプルコードは次のとおりです:
コードは次のとおりです:
クラスデバイス{
//...
パブリック関数 __invoke($data) {
echo $data;
}
//...
}
$device = new Device(new Battery(), 'iMagic');
$device('test');
// $device->__invoke('test') と同等
// 出力: test
その他:__autoload()
__autoload() メソッドは魔法のメソッドではありませんが、非常に便利です。ただし、PHP バージョンの更新により、この関数は推奨されなくなり、spl_auto_register() 関数に置き換えられました。
。