__get()
および
__set()
を使用することです。
それぞれのアプローチには長所と短所があります。それらを見てみましょう...
パブリックプロパティの使用例:
class Foo { public $bar; } $foo = new Foo(); $foo->bar = 1; $foo->bar++;
この例では、 barはFooクラスのパブリックプロパティです。 このアプローチを使用すると、このプロパティを好きなように操作して、任意のデータを保存できます。
公共財産の利点
- ゲッターやセッターに比べて、印刷するテキストがはるかに少なくなります!
- このコードは、getterおよびsetter呼び出しよりも読みやすく、扱いやすいように見えます。
- (
set
またはget
代わりに)パブリックプロパティへの呼び出しは、メソッド呼び出しよりも高速であり、メモリ使用量も少なくなりますが、長いループで何度もメソッドを呼び出すまで利点はほとんど見えません。 - パブリックプロパティを持つオブジェクトは、いくつかのPHP関数(
http_build_query
など)のパラメーターとして使用できます。
パブリックプロパティのデメリット
- プロパティに含まれるデータを正確に制御する方法はありません。このクラスのメソッドにとって不適切なデータをそれらに入力することは非常に簡単です。 たとえば、クラスの作成者とは異なるサードパーティの開発者がクラスを使用する場合、クラスの内部構造を認識していない(および義務を負わない)ために問題が発生する可能性があります。 最終的には、数か月後に著者自身が自分が書いたコードのロジックを忘れてしまうこともよくあります。
- APIでパブリックプロパティを使用する場合、インターフェイスを使用してこれを行うことはできません。PHPインターフェイスではメソッドシグネチャの定義のみが許可されているためです。
ゲッターとセッターの使用例:
class Foo { private $bar; public function getBar() { return $this->bar; } public function setBar($bar) { $this->bar = $bar; } } $foo = new Foo(); $foo->setBar(1); $foo->setBar($foo->getBar() + 1);
ここの
bar
プロパティはプライベートです。この点で、直接アクセスすることはできません。 プロパティの値を取得するには、
getBar
または
setBar
を使用してプロパティに値を割り当てる必要があります。 入力データが完全に正しいことを確認できるように、これらのメソッドには検証に適切な機能が含まれている場合があります。
ゲッターとセッターの利点
- ゲッターとセッターを使用すると、オブジェクトのプロパティに含まれるデータを正確に制御し、不正な値を拒否できます。
- プロパティの値を設定または取得する前に追加の操作を実行することもできます(たとえば、このプロパティを更新すると、ユーザーへの通知などのアクションが発生する場合)。
- オブジェクトまたは配列である値を設定する場合、関数シグネチャで変数のタイプを明示的に指定できます(
public function setBar(Bar $bar)
注意してください)。 残念ながら、PHPではint
およびstring
型で同じことを行うことはできません! - プロパティ値を外部ソースまたはランタイムから取得する必要がある場合、データの遅延読み込みを使用できます。この方法では、データを読み込むために必要なリソースがプロパティ値の受信中に直接使用されます。 もちろん、この場合、注意が必要です。プロパティにアクセスするたびに外部ソースからデータを受信しないでください。 個別に行うよりも、データベースを1回呼び出して、すべてのプロパティの値を一度に入力する方が適切です。
- プロパティを読み取り専用または書き込み専用にするには、ゲッターのみまたはセッターのみを作成します。
- APIで表示するために、インターフェイスにゲッターとセッターを追加できます。
ゲッターとセッターの欠点
- プロパティへの直接アクセスを使用する開発者にとって、ゲッターとセッターは本当に頭痛の種のようです! プロパティごとに、プロパティ自体、getterおよびsetterを定義する必要があります。 コードでこのプロパティを使用するには、追加のメソッド呼び出しを行う必要があります-
$foo->bar++;
と書く方がはるかに簡単$foo->bar++;
代わりに$foo->setBar($foo->getBar() + 1);
(もちろん、別のメソッド$foo->incrementBar();
追加でき$foo->incrementBar();
) - 上記のように、メソッドの呼び出しにはわずかな追加費用がかかります。
- ゲッターとセッターの名前は、通常、動詞
get
とset
で始まりget
が、これらの動詞は他のメソッドでも使用できます。これらのメソッドは、クラスのプロパティに決して関連しません。
マジックゲッターとセッターの使用例:
class Foo { protected $bar; public function __get($property) { switch ($property) { case 'bar': return $this->bar; //etc. } } public function __set($property, $value) { switch ($property) { case 'bar': $this->bar = $value; break; //etc. } } } $foo = new Foo(); $foo->bar = 1; $foo->bar++;
この場合、
bar
プロパティはパブリックではありませんが、コードではまるでパブリックであるかのように使用されます。 PHPは、対応するパブリックプロパティを見つけることができない場合、対応するマジックメソッド(
__get()
値を取得し、
__set()
値を設定します)を
__set()
ます。 このアプローチは妥協点のように思えるかもしれませんが、重大な欠点があります(以下の欠点をご覧ください!)。
__get()
および
__set()
メソッドはパブリックプロパティに対して呼び出されず、プロパティが
protected
または
private
としてマークさ
protected
、スコープ外にある場合、またはプロパティが定義されていない場合に
__get()
れることにも注意して
__get()
。
マジックゲッターとセッターの利点
- プロパティを直接操作して(パブリックのように)、どのデータをどのプロパティに保存するかを完全に制御できます。
- 通常のゲッターとセッターを使用するのと同様に、プロパティが使用されるときに追加の操作を実行できます。
- 遅延データ読み込みを使用できます。
- プロパティを読み取り専用または書き込み専用にすることができます。
- マジックメソッドを使用して、定義されていないプロパティへのすべての呼び出しをインターセプトし、それらを何らかの方法で処理できます。
魔法のゲッターとセッターの欠点
-
マジックメソッドの欠点は、プロパティを使用可能(「表示」)にしないことです。クラスを使用または拡張するには、クラスに含まれるプロパティを「知る」だけです。ほとんどの場合、これは不可能です(メモ帳がIDEであると考えている筋金入りのプログラマーでない限り!)。ただし、上記の利点がこの制限を上回る場合もあります。1人のコメント者が指摘したように、この欠陥はphpDocタグ@property-read
、@property-read
、および@property-write
を使用して修正できます。 かっこいい。
使用するアプローチ
明らかに、ゲッターとセッターには多くの重要な利点があり、一部の人々はそれらを常に使用すべきだと考えています(特に
Java
バックグラウンドを持つ人!)。 しかし、私の意見では、これは言語の自然な発展に違反し、その過度の複雑さと詳細は、たとえそれが必要ではない場合でも、私と一緒に働くことを余儀なくさせます(普通のゲッターとセッターがプロパティを取得して設定するだけで何もしない場合、私を悩ませます)。 そのような場合、パブリックプロパティを使用しようとします。より厳密に制御する必要がある重要なプロパティ、または遅延データの読み込みを使用する必要がある場合は、ゲッターとセッターを使用します。
他の選択肢?
PHPを学習する前に、C#を使用しました。 C#では、すべてのプロパティにアクセスメソッドがありますが、メソッドとして呼び出す必要はありません。プロパティを直接操作すると、対応するメソッドが魔法のように呼び出されます。 これは、PHPのマジックメソッド
__get()
および
__set()
に多少似ていますが、プロパティは定義されたままで、アクセス可能です。 これは黄金の意味であり、PHPで同様の機会が見られることは非常に良いことです。
悲しいことに、プロパティアクセスメソッドを定義するための同様の構文でC#を実装する必要があるRFCは、必要な票の3分の2を獲得しませんでした: wiki.php.net/rfc/propertygetsetsyntax-v1.2それだけです!