ホームページ  >  記事  >  php教程  >  PHP 5 のオブジェクト オーバーロード テクノロジを探索する

PHP 5 のオブジェクト オーバーロード テクノロジを探索する

WBOY
WBOYオリジナル
2016-06-21 08:50:58845ブラウズ

オブジェクト オーバーロード テクノロジは、PHP 5 で導入されました。この記事では、メソッド __call()、__set()、および __get() をオーバーロードする可能性について検討します。オーバーロード理論について簡単に説明した後、2 つの例を通して本題に進みます。最初の例は永続ストレージ クラスを実装することであり、2 番目の例は動的ゲッター/セッターを実装する方法を見つけることです。

1. オブジェクトのオーバーロードとは何ですか?

PHP でオブジェクトのオーバーロードについて話すときは、次の 2 つのタイプを区別する必要があります。

◆メソッドのオーバーロード

◆属性のオーバーロード

メソッドのオーバーロードの場合、マジック メソッド __call() を定義する必要があります。これは、対応するクラスの未定義メソッドへの一般的な呼び出しを実装します。この一般メソッドは、クラス内の未定義のメソッドにアクセスする場合にのみ呼び出されます。メソッドのオーバーロードを行わない場合、次の例では PHP に致命的なエラー メッセージが表示されます。/some/directory/example.php の 9 行目で未定義のメソッド ThisWillFail::bar() を呼び出し、プログラムの実行を中止します:


  1. 		<?php  
  2. class ThisWillFail {
  3. パブリック関数 foo() {
  4. 「Hello World!」を返します
  5. }
  6. }
  7. $class = 新しい ThisWillFail
  8. $class->bar();
  9. ?>
メソッドのオーバーロードを利用すると、コードはこの呼び出しをキャッチして適切に処理できます。プロパティのオーバーロードはメソッドのオーバーロードに似ています。この場合、クラスは、クラス内で明示的に定義されていないクラスのプロパティに読み取り/書き込み操作をリダイレクトします (プロキシとも呼ばれます)。ここでの特殊なメソッドは __set() と __get() です。エラー報告レベルに応じて、PHP トランスレータは通常、未定義のプロパティにアクセスしたときに通知を発行するか、変数を延期して潜在的に定義します。

属性のオーバーロードを使用する場合、トランスレーターは、未定義の属性を設定するときに __set() を呼び出し、未定義の属性値にアクセスするときに __get() を呼び出すことができます。要約すると、オーバーロード技術を使用すると、PHP などの動的言語を使用する場合のソフトウェア開発時間を大幅に短縮できます。

2. 永続ストレージの例

次のコードは、プロパティ オーバーロード テクノロジを使用して、前述の永続ストレージ クラスを 50 行未満の PHP コードで実装します。永続的という用語は、クラスがデータ構造から要素を記述でき、基礎となるストレージ システムとの同期を維持できることを意味します。コーディング用語では、外部コードはクラスを使用してデータベース テーブルから行を選択できます。

このようにして、プログラムの実行中に、クラスの属性に直接アクセスして、行内の要素を操作 (読み取り/フェッチ) できます。スクリプトの最後で、PHP は更新された行データをデータベースに送り返します。次のコードを注意深く検討すると、属性のオーバーロードとは何かを理解するのに役立ちます。


  1. 		<?php  
  2.  //PEAR を組み込む DB パッケージ
  3.  require_once「DB.php」;  
  4.  クラス 永続性 {
  5. private $data = array();  
  6. private $table = 「ユーザー」;  
  7. public 関数 __construct($user) {
  8.  $this->dbh = DB::Connect("mysql://user:password@localhost/database");  
  9.  $query = 「ID、名前、メールアドレス、国を FROM から選択」  
  10.  $this->table 。 「 WHERE 名前 = ?」;  
  11.  $this->data = $this->dbh->getRow($query, array($user),
  12.  DB_FETCHMODE_ASSOC);  
  13. }
  14. public 関数 __get($member) {
  15.  if (isset($this->data[$member])) {
  16. return $this->data[$member];  
  17.  }
  18. }
  19.  
  20. public function __set($member, $value) {
  21.  // データセットの ID はただの説明です
  22.  if ($member == "id") {
  23. 戻る;  
  24.  }
  25.  if (isset($this->data[$member])) {
  26. $this->data[$member] = $value;  
  27.  }
  28. }
  29. public 関数 __destruct() {
  30.  $query = "更新 " 。 $this->table 。 " SET name = ?,
  31.  メールアドレス = ?、国 = ? WHERE id = ?";
  32.  $this->dbh->query($query, $this->name, $this->email,
  33.  $this->country, $this->id);  
  34. }
  35.  }
  36.  $class = new Persistable("Martin Jansen");  
  37.  $class->name = "ジョン ドゥ";  
  38.  $class->country = "米国";  
  39.  $class->email = "john@example.com";  
  40. ?>

最初の問題は、おそらく PHP 5 に導入された新しいストラクチャー メソッドである __construct() です。コンストラクタの方法には多くの知識が必要ではなく、使用するタイプの例外を作成することができます。ここではパラメータを使用しており、このパラメータに基づいてデータベースを実行していることに注意してください。監査結果の値をプロパティ $data に渡します。

次に、プログラムは 2 つの特別なメソッド __get() と __set() を定義します。これはすでによく知られているものです。__get() は、未定義のプロパティ値を取得するために使用され、__set() は、未定義のプロパティを変更するために使用されます。プロパティ値。

これは、いつでも、このような方法で、クラスのプロパティを直接変更するのではなく、プロパティの数集合 $data 内の情報を管理する、保存されたクラス内の未定のプロパティを取得/書き込みすることを意味します。量 $data には、データベースからの一行が含まれています!)。

この種の最後のメソッドは、__construct() のエディター ストラクチャー__destruct() です。PHP は、通常、PHP の実行がすぐに完了するときである「スクリプト中断段階」で、パラメーターを調整します。これは、前の同期 (同期) の内容です。

おそらく、ここでのコードは PEAR のデータベース抽象化層パッケージを使用していることは、データ アクセス許可と同様の方法で使用されていることがわかります。

しかし、注意深く観察すると、この持続性ストレージの説明は、LEFT JOIN やその他のデータベース操作技術の使用など、より複雑なデータ モデルを考慮せずに、単に 1 つのデータベース テーブルを対象としていることがわかります。必須ではありませんこのように考えると、プロパティの再ロードを使用して、必要なコードを追加するだけで、その永続的なストレージ タイプで独自の理想的なデータ モデルを使用できます。

また、HTML の構築は PHP で頻繁に使用されるため、このような状況では、アライナ パラメータの特性により、対応する問題情報が表示されないという小さな問題もあります。構造化器の前にすでに完了しています。

为解决这个问题,你可以把__destruct()重命名为象saveData()这样的名字并在调用脚本的某处手工执行这一方法。这对于类的持续性存储的概念并没有任何改变;仅是多写几行代码而已。作为选择,你还可以在析构器中使用函数error_log()来记录下属于系统范围的错误记录文件中的错误信息。属性重载的工作机制就是这样。下面我们讨论一下方法重载。

 三、方法重载举例

1. 动态的Getter/Setter方法

下列代码实现了"动态"getter/setter方法以借助于方法重载的帮助来控制类。下面我们结合源代码进行分析:


  1. 		<?php  
  2.  class DynamicGetterSetter {  
  3. private $name = "Martin Jansen";  
  4. private $starbucksdrink = "Caramel Cappuccino Swirl";  
  5. func  

  1. 		tion __call($method, $arguments) {  
  2.  $prefix = strtolower(substr($method, 0, 3));  
  3.  $property = strtolower(substr($method, 3));  
  4.  if (empty($prefix)  empty($property)) {  
  5. return;  
  6.  }  
  7.  if ($prefix == "get" && isset($this->$property)) {  
  8. return $this->$property;  
  9.  }  
  10.  if ($prefix == "set") {  
  11. $this->$property = $arguments[0];  
  12.  }  
  13. }  
  14.  }  
  15.  $class = new DynamicGetterSetter;  
  16.  echo "Name: " . $class->getName() . "\n";  
  17.  echo "Favourite Starbucks flavour: " . $class->getStarbucksDrink() . "\n\n";  
  18.  $class->setName("John Doe");  
  19.  $class->setStarbucksDrink("Classic Coffee");  
  20.  echo "Name: " . $class->getName() . "\n";  
  21.  echo "Favourite Starbucks flavour: " . $class->getStarbucksDrink() . "\n\n";  
  22. ?>  

很明显,这里的两个属性$name和$starbucksdrink都是私有的,就是说从类的外部是不能够存取这些属性的。在面向对象的编程中,实现公共的getter/setter方法来存取或修改非公共属性的值是很经常的事情。实现这些是单调的事情,且相当耗费时间和精力。

借助于方法重载可以容易得解决这个问题。不是为每个属性实现getter/setter方法,上面只实现了一个通用的__call()方法。这意味着当调用一个未定义的getter/setter方法如setName()或者getStarbucksdrink()时,PHP不会产生一个致命错误而流产,而是执行(或者代理到)魔术般的__call()方法。这是些简单介绍,下面我们对__call()作一下深入分析。

2. 详细分析__call()方法

__call()的第一个参数是原始的且尚未确定的方法(如setName),第二个参数是一个数字索引的一维数组,它包含了原始方法的所有参数。用两个参数("Martin"和42)调用一个未定义的方法将产生下面数组:


  1. 		$class->thisMethodDoesNotExist("Martin", 42);  
  2. /导向__call()的第二个参数  
  3. Array  
  4. (  
  5. [0] => Martin  
  6. [1] => 42  
  7. )  

在方法__call()内部,如果原始方法以get或者set开头,则要进行某种计算以确定是否代码调用的是一个getter/setter方法。而且,这种方法还要进一步分析方法名的另外一组成部分(除去开始的三个字符),因为后面这部分字符串正代表getter/setter参照的属性的名字。

如果方法名中指示有一个getter/setter,那么该方法或者返回相应的属性值,或者设置原始方法的第一个参数的值。如果没有的话,它不做任何事情,继续执行程序,好象没有事情发生。

3. 实现目标

本質的には、任意のプロパティに対応して、コードで任意の getter/setter メソッドを動的に呼び出すことができるメソッドが存在します。このアルゴリズムが存在します。これは、プログラムのプロトタイプを短期的に開発する場合に便利です。開発者は、ゲッター/セッターの実装に多くの時間を費やす代わりに、API のモデル化とアプリケーションが基本的に正しいことの確認に集中できます。 __call() メソッドを抽象クラスに組み込むと、将来の PHP プロジェクト開発でコードを再利用できる可能性もあります!

4. 欠点を超えて

メリットとデメリットがあります。上記のアプローチにはいくつかの欠点があります。大規模なプロジェクトでは、API 構造を追跡するために phpDocumentor などのツールを使用する場合があります。上記で紹介した動的メソッドでは、もちろん、すべてのゲッター/セッター メソッドが自動生成されたドキュメントに表示されるわけではありません。これについては、これ以上説明する必要はありません。

もう 1 つの欠点は、クラス外のコードがクラス内のすべてのプライベート プロパティにアクセスできることです。実際のゲッター/セッター メソッドを使用する場合、外部コードからアクセスできるプライベート プロパティと、クラスの外部には表示されない「実際の」プライベート プロパティを区別することができます。これは、メソッドのオーバーロードがあり、仮想ゲッターとセッターがあるためです。メソッドを使用できます。

結論

この記事では、2 つの例を通じて、PHP 5 におけるオブジェクトのオーバーロードの 2 つの状況を詳細に分析します。この記事の方法が PHP プログラミングの効率向上に役立つことを強く願っています。同時に、この方法の欠点も明確に理解していただけるはずです。



声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。