ホームページ  >  記事  >  バックエンド開発  >  Yiiのプロパティの詳細な説明

Yiiのプロパティの詳細な説明

*文
*文オリジナル
2017-12-29 19:04:431892ブラウズ

この記事では主に PHP の Yii フレームワークのプロパティ (Property) を紹介し、プロパティを実装する手順を詳しく説明します。必要な友人は参照してください。お役に立てれば幸いです。

PHPでは、クラスのメンバー変数はプロパティとも呼ばれます。これらはクラス定義の一部であり、インスタンスの状態を表すために (つまり、クラスの異なるインスタンスを区別するために) 使用されます。具体的な実践では、属性の読み取りと書き込みに少し特殊なメソッドを使用したいことがよくあります。たとえば、毎回ラベル属性に対してトリム操作を実行する必要がある場合は、次のコードを使用してそれを実現できます:

$object->label = trim($label);

上記のコードの欠点は、ラベル属性が変更されている限り、トリム( ) 関数を再度呼び出す必要があります。将来、最初の文字を大文字にするなど、他の方法でラベル属性を処理する必要がある場合は、ラベル属性に値を割り当てるすべてのコードを変更する必要があります。このコードの重複はバグを引き起こす可能性があるため、この行為は可能な限り避ける必要があることは明らかです。

この問題を解決するために、Yii は yiibaseObject と呼ばれる基本クラスを導入します。これは、クラス内のゲッターおよびセッター (リーダーおよびセッター) メソッドに基づくプロパティの定義をサポートします。クラスがこの機能をサポートする必要がある場合、yiibaseObject またはそのサブクラスを継承するだけで済みます。

補足: Yii フレームワークのほぼすべてのコアクラスは、yiibaseObject またはそのサブクラスを継承します。これは、コア クラスでゲッター メソッドまたはセッター メソッドを見つけたときはいつでも、プロパティと同じように呼び出すことができることを意味します。
ゲッター メソッドは名前が get で始まるメソッドであり、セッター メソッド名は set で始まります。メソッド名の get または set 以降の部分は、プロパティの名前を定義します。以下のコードに示すように、ゲッター メソッド getLabel() とセッター メソッド setLabel() は、ラベル属性を操作します:

namespace app\components;

use yii\base\Object;

class Foo extend Object
{
  private $_label;

  public function getLabel()
  {
    return $this->_label;
  }

  public function setLabel($value)
  {
    $this->_label = trim($value);
  }
}

(詳細説明: ゲッター メソッドとセッター メソッドは、label という名前の属性を作成します。この例では、それはポイントです)

ゲッター/セッターで定義されたプロパティは、クラスのメンバー変数と同じように使用されます。 2 つの主な違いは、このプロパティが読み取られると、対応するゲッター メソッドが呼び出され、プロパティに値が割り当てられると、対応するセッター メソッドが呼び出されることです。例:

// 等效于 $label = $object->getLabel();
$label = $object->label;

// 等效于 $object->setLabel('abc');
$object->label = 'abc';

ゲッターのみを定義し、セッターを定義しないプロパティは読み取り専用プロパティです。このようなプロパティに割り当てようとすると、yiibaseInvalidCallException (無効な呼び出し) 例外が発生します。同様に、ゲッター メソッドを使用せずにセッター メソッドのみで定義されたプロパティは書き込み専用プロパティであり、そのようなプロパティを読み取ろうとした場合も例外がトリガーされます。書き込み専用プロパティを使用するケースはほとんどありません。

ゲッターとセッターを通じて定義されたプロパティには、いくつかの特別なルールと制限もあります。

そのようなプロパティの名前は、大文字と小文字が区別されません。たとえば、$object->label と $object->Label は同じプロパティです。 PHP メソッド名では大文字と小文字が区別されないためです。
このタイプの属性の名前がクラスのメンバー変数と同じ場合は、後者が優先されます。たとえば、上記の Foo クラスに label メンバー変数があり、$object->label = 'abc' に値を割り当てると、セッター setLabel() メソッドの代わりにメンバー変数に割り当てられるとします。
このタイプのプロパティは、可視性 (アクセス制限) をサポートしていません。プロパティの getter メソッドと setter メソッドが public、protected、または private であるかどうかは、プロパティの可視性には影響しません。
このタイプのプロパティのゲッター メソッドとセッター メソッドは、非静的メソッドとしてのみ定義できます。静的メソッド (静的) として定義されている場合、同じように処理されません。
最初に述べた質問に戻りますが、trim() 関数をどこでも呼び出すのではなく、setter setLabel() メソッド内で 1 回呼び出すだけで済みます。ラベルの最初の文字を大文字にするという新しい要件が発生した場合は、他のコードには触れずに setLabel() メソッドを変更するだけで済みます。

属性を実装する手順

オブジェクトの存在しないメンバー変数を読み書きする場合、__get() __set() が自動的に呼び出されることはわかっています。 Yii はこれを利用して属性のサポートを提供します。上記のコードから、オブジェクトのプロパティにアクセスすると、Yii が getpropertyname() という関数を呼び出すことがわかります。たとえば、SomeObject->Foo は SomeObject->getFoo() を自動的に呼び出します。プロパティが変更されると、対応するセッター関数が呼び出されます。 たとえば、SomeObject->Foo = $someValue は SomeObject->setFoo($someValue) を自動的に呼び出します。

したがって、プロパティを実装するには、通常、次の 3 つの手順があります:

  • yiibaseObject から継承します。

  • このプロパティを保存するには、プライベート メンバー変数を宣言します。

  • 上記のプライベート メンバー変数にアクセスして変更するためのゲッター関数またはセッター関数、あるいはその両方を提供します。 ゲッターのみが提供されている場合、プロパティは読み取り専用であり、セッターのみが提供されている場合、プロパティは書き込み専用です。

次の Post クラスは、読み取りおよび書き込み可能な属性 title を実装します:

class Post extends yii\base\Object  // 第一步:继承自 yii\base\Object
{
  private $_title;         // 第二步:声明一个私有成员变量

  public function getTitle()    // 第三步:提供getter和setter
  {
    return $this->_title;
  }

  public function setTitle($value)
  {
    $this->_title = trim($value);
  }
}

理論的に言えば、private $_title を public $title として書き込むと、 $post->title の読み取りと書き込みも可能になります。しかし、これは次の理由から良い習慣とは言えません:

クラスのカプセル化が失われました。 一般に、メンバー変数を外部から見えないようにすることは、良いプログラミング方法です。 ここからは表示されないかもしれませんが、いつかユーザーにタイトルを変更させたくない場合、どうすれば変更できますか? タイトルがコード内で直接変更されないようにする方法は? セッターが提供されている場合、そのセッターが削除されている限り、ヘッダーへの未クリーンな書き込みがあると例外がスローされます。 public $titleメソッドを使用している場合、private $titleに変更することで書き込み例外を確認できますが、読み出しも禁止されます。
タイトルを書く場合、スペースを削除したい。 setter メソッドを使用すると、上記のコード スニペットのように、この場所で trim() を呼び出すだけで済みます。 ただし、パブリック $title メソッドを使用する場合は、write ステートメントごとにtrim() が呼び出されるのは間違いありません。 何も欠けていないことを保証できますか?
そのため、 public $title を使うのは手っ取り早いだけで簡単そうに見えますが、今後の修正が面倒になります。 それは悪夢と言ってもいい。これがソフトウェア エンジニアリングの意味であり、特定の方法でコードの保守と変更を容易にします。 一見不必要に思えるかもしれませんが、実際、損失を被った友人や、クライアントの上司から前のプログラマーが書いたコードの修正を強要され、親戚に挨拶した友人は皆、これが非常に必要だと感じるでしょう。

しかし、この世に絶対はありません。 __get() と __set() はすべてのメンバー変数を調べられるため、一致するメンバー変数が見つからない場合にのみ呼び出されます。 したがって、その効率はメンバー変数を使用する場合よりも本質的に低くなります。データ構造、データ コレクションなどが表現され、読み取り/書き込み制御が必要ない単純な状況では、メンバー変数を属性とみなすことができるため、効率が向上します。

効率を向上させるもう 1 つの小さなトリックは、$pro = $object->pro の代わりに $pro = $object->getPro() を使用し、$object -> の代わりに $objcect->setPro($value) を使用することです。 ;pro = $value 。 これは機能的にはまったく同じですが、__get() と __set() の使用を回避します。これは、トラバーサル プロセスをバイパスするのと同じです。

ここで誰かが私を叱るべきだと思いますが、Yii は開発者の便宜のために属性メカニズムを最終的に実装しましたが、いわゆる効率を向上させるために独自の方法を使用する方法を教えるためにここにいます。 確かに、開発の利便性と実行の高効率の間には、ある種の矛盾があります。私の個人的な考え方としては、利便性を第一に考え、Yii が作り出した便利な条件を有効に活用したいと考えています。効率に関しては、フレームワーク自体がもっと注意を払う必要がありますが、余分なコードを書かない限りは問題ありません。

しかし、Yii のフレームワークでは $app->request のようなコードはめったに出現せず、代わりに $app->getRequest() が使用されるのでご安心ください。 つまり、フレームワーク自体は効率性を重視しており、利便性は開発者に委ねられています。 つまり、ここで紹介するのは単なる知識であり、それを使用するかどうか、どのように使用するかは完全にあなた次第です。

注意点:

__get() __set() を自動的に呼び出すタイミングは、存在しないメンバー変数にアクセスする場合にのみ発生するためです。 したがって、メンバ変数 public $title が定義されている場合、getTitle() setTitle() が定義されていても呼び出されません。 $post->title は直接 $title を指すため、 __get() __set() は呼び出されません。根元から切り離されてしまいました。
PHP はクラス メソッドの大文字と小文字を区別しないため、$post->getTitle() と $post->gettitle() は同じ関数を呼び出します。 したがって、$post->title と $post->Title は同じプロパティです。つまり、属性名でも大文字と小文字は区別されません。
__get() __set() は両方とも public であるため、getTitle() setTitle() が public、private、または protected として宣言されているかどうかは意味がありません。また、外部からアクセスすることもできます。したがって、すべてのプロパティは公開されます。
__get() も __set() も静的ではないため、静的属性を使用する方法はありません。
Object のその他の属性関連メソッド

__get() __set() に加えて、yiibaseObject は属性の使用を容易にする次のメソッドも提供します:

  • __isset() は属性値が正しいかどうかをテストするために使用されます。 isset($object->property) の null が自動的に呼び出されます。 このプロパティには対応するゲッターが必要であることに注意してください。

  • __unset() はプロパティ値を null に設定するために使用され、unset($object->property) のときに自動的に呼び出されます。 このプロパティには対応するセッターが必要であることに注意してください。

  • hasProperty() は、特定のプロパティが存在するかどうかをテストするために使用されます。つまり、ゲッターまたはセッターが定義されます。 hasProperty() のパラメータ $checkVars = true (デフォルトは true) の場合、前述の public $title など、同じ名前のメンバー変数もこのプロパティを持つとみなされます。

  • canGetProperty() は、プロパティが読み取り可能かどうかをテストします。パラメーター $checkVars の意味は上記と同じです。ゲッターが定義されている限り、プロパティは読み取り可能です。 また、 $checkVars が true の場合。クラスがメンバー変数を定義している限り、メンバー変数がパブリック、プライベート、または保護されているかどうかに関係なく、それらは読み取り可能であるとみなされます。

  • canSetProperty() は、プロパティが書き込み可能かどうかをテストします。パラメーター $checkVars の意味は上記と同じです。 setter が定義されていれば、プロパティを書き込むことができます。 同時に、 $checkVars は true になります。次に、クラスがメンバー変数を定義している限り、メンバー変数がパブリック、プライベート、または保護されているかどうかに関係なく、書き込み可能とみなされます。

  • ObjectとComponent

yiibaseComponent は yiibaseObject を継承しているため、プロパティなどの基本的な機能も備えています。

ただし、Componentではイベントやビヘイビアも導入しているため、単純にObjectのプロパティ実装メソッドを継承するのではなく、同じ仕組みに基づいて __get() __set() などの関数をオーバーロードします。ただし、実装メカニズムの点では、それらは同じです。これは理解には影響しません。

前に述べたように、Yii は公式にはコンポーネントベースのフレームワークとして位置付けられています。可視コンポーネントの概念は Yii の基礎です。 Yii のソースコードまたは API ドキュメントを読むことに興味がある場合は、Yii のほぼすべてのコアクラスが yiibaseComponent から派生 (継承) されていることがわかります。

Yii1.1 にはすでにコンポーネントがあり、当時は CComponent でした。 Yii2 は、Yii1.1 の CComponent を 2 つのクラス、yiibaseObject と yiibaseComponent に分割します。

その中で、Object は比較的軽量であり、ゲッターとセッターを通じてクラスのプロパティを定義します。コンポーネントはオブジェクトから派生し、イベントと動作をサポートします。したがって、Component クラスには 3 つの重要な特性があります:

  • property

  • event

  • behavior

これら 3 つは多かれ少なかれ理解できたと思います。この機能は、機能を強化し拡張するための重要なエントリ ポイントです。クラス関数とクラス動作の変更。 したがって、コンポーネントは Yii において非常に高い地位を占めています。

コンポーネントは、より多くの機能と利便性を提供しながら、イベントとビヘイビアの 2 つの機能を追加しました。これにより、ある程度の効率を犠牲にしながらも開​​発が容易になります。 何らかのデータを表すクラスなど、開発中にイベントとビヘイビアの 2 つの機能を使用する必要がない場合。 すると、Componentからの継承はできず、Objectからの継承となります。 一般的なアプリケーション シナリオでは、ユーザーが入力したデータのセットを表す場合はオブジェクトを使用します。 そして、オブジェクトの挙動やその処理に応答するイベントを扱う必要がある場合には、コンポーネントを使用するのが間違いありません。 効率の点では、Object の方がネイティブ PHP クラスに近いため、可能な場合は Object を最初に使用する必要があります。

関連する推奨事項:

Yiiの動作メカニズムとルーティングの詳細な説明

YiiがURL内のindex.phpを隠す方法

PHP Yiiフレームワークのデータベースクエリ操作の概要

以上がYiiのプロパティの詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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