Heim  >  Artikel  >  Backend-Entwicklung  >  Eigenschaft im Yii-Framework von PHP

Eigenschaft im Yii-Framework von PHP

小云云
小云云Original
2017-11-13 11:50:281308Durchsuche

Yii ist ein leistungsstarkes, komponentenbasiertes PHP-Framework für die Entwicklung umfangreicher Webanwendungen. Yii ist in striktem OOP geschrieben und verfügt über vollständige Bibliotheksreferenzen und umfassende Tutorials. Von MVC, DAO/ActiveRecord, Widgets, Caching, hierarchischem RBAC, Webdiensten bis hin zu Theming, I18N und L10N bietet Yii fast alles, was für die heutige Web 2.0-Anwendungsentwicklung benötigt wird. Tatsächlich ist Yii eines der effizientesten PHP-Frameworks.

Yii ist ein leistungsstarkes PHP5-Framework für die Entwicklung von Webanwendungen. Mit einem einfachen Befehlszeilentool kann yiic schnell ein Webanwendungscode-Framework erstellen. Entwickler können Geschäftslogik basierend auf dem generierten Code-Framework hinzufügen, um die Anwendungsentwicklung schnell abzuschließen.

In PHP werden Klassenmitgliedsvariablen auch Eigenschaften genannt. Sie sind Teil der Klassendefinition und werden verwendet, um den Zustand einer Instanz darzustellen (d. h. um zwischen verschiedenen Instanzen der Klasse zu unterscheiden). In der konkreten Praxis möchten wir häufig eine etwas speziellere Methode zum Lesen und Schreiben von Attributen verwenden. Wenn Sie beispielsweise jedes Mal einen Trimmvorgang für das Etikettenattribut durchführen müssen, können Sie dies mit dem folgenden Code erreichen:

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

Der Nachteil des obigen Codes besteht darin, dass das Etikettenattribut so lange wie möglich ist geändert wird, muss die Funktion trim() erneut aufgerufen werden. Wenn Sie das Etikettenattribut in Zukunft auf andere Weise behandeln müssen, z. B. durch Großschreibung des ersten Buchstabens, müssen Sie den gesamten Code ändern, der dem Etikettenattribut Werte zuweist. Diese Duplizierung des Codes kann zu Fehlern führen und diese Praxis muss natürlich wann immer möglich vermieden werden.

Um dieses Problem zu lösen, führt Yii eine Basisklasse namens yiibaseObject ein, die die Definition von Eigenschaften basierend auf Getter- und Setter-Methoden (Reader und Setter) innerhalb der Klasse unterstützt. Wenn eine Klasse diese Funktion unterstützen muss, muss sie nur yiibaseObject oder seine Unterklassen erben.

Ergänzung: Fast jede Kernklasse des Yii-Frameworks erbt von yiibaseObject oder seinen Unterklassen. Das bedeutet, dass Sie jedes Mal, wenn Sie eine Getter- oder Setter-Methode in einer Kernklasse sehen, diese wie eine Eigenschaft aufrufen können.
Getter-Methoden sind Methoden, deren Namen mit get beginnen, während die Namen von Setter-Methoden mit set beginnen. Der Teil nach get oder set im Methodennamen definiert den Namen der Eigenschaft. Wie im folgenden Code gezeigt, bearbeiten die Getter-Methode getLabel() und die Setter-Methode setLabel() das Label-Attribut:

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);
  }
}

(Detaillierte Erklärung: Die Getter- und Setter-Methoden erstellen ein Attribut namens label, In diesem Beispiel zeigt es auf eine private interne Eigenschaft (_label).

Die durch Getter/Setter definierten Eigenschaften werden auf die gleiche Weise wie Klassenmitgliedsvariablen verwendet. Der Hauptunterschied zwischen den beiden besteht darin, dass beim Lesen dieser Eigenschaft die entsprechende Getter-Methode aufgerufen wird, und wenn der Eigenschaft ein Wert zugewiesen wird, wird die entsprechende Setter-Methode aufgerufen. Beispiel:

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

Eigenschaften, die nur Getter und keine Setter definieren, sind schreibgeschützte Eigenschaften. Der Versuch, einer solchen Eigenschaft eine Zuweisung zuzuweisen, führt zu einer Ausnahme vom Typ yiibaseInvalidCallException (ungültiger Aufruf). Ebenso sind Eigenschaften, die nur mit Setter-Methoden, aber ohne Getter-Methoden definiert wurden, schreibgeschützte Eigenschaften, und Versuche, solche Eigenschaften zu lesen, lösen ebenfalls eine Ausnahme aus. Es gibt fast keine Fälle für die Verwendung von schreibgeschützten Eigenschaften.

Eigenschaften, die durch Getter und Setter definiert werden, unterliegen auch einigen besonderen Regeln und Einschränkungen:

Bei den Namen solcher Eigenschaften wird die Groß-/Kleinschreibung nicht beachtet. Beispielsweise sind $object->label und $object->Label dieselbe Eigenschaft. Weil bei PHP-Methodennamen die Groß-/Kleinschreibung nicht beachtet wird.
Wenn der Name dieses Attributtyps mit dem Namen der Klassenmitgliedsvariablen übereinstimmt, hat letztere Vorrang. Angenommen, die obige Foo-Klasse verfügt über eine Label-Mitgliedsvariable und weist dann $object->label = 'abc' einen Wert zu, der dieser Mitgliedsvariablen und nicht der Setter-setLabel()-Methode zugewiesen wird.
Diese Art von Eigenschaft unterstützt keine Sichtbarkeit (Zugriffsbeschränkungen). Ob die Getter- und Setter-Methoden einer Eigenschaft öffentlich, geschützt oder privat sind, hat keinen Einfluss auf die Sichtbarkeit der Eigenschaft.
Die Getter- und Setter-Methoden dieses Eigenschaftstyps können nur als nicht statisch definiert werden. Wenn sie als statische Methoden (statisch) definiert sind, werden sie nicht auf die gleiche Weise verarbeitet.
Um auf das eingangs erwähnte Problem zurückzukommen: Anstatt die Funktion trim() überall aufzurufen, müssen wir sie jetzt nur noch einmal innerhalb der Setter-Methode setLabel() aufrufen. Wenn eine neue Anforderung besteht, dass der erste Buchstabe der Bezeichnung großgeschrieben werden muss, müssen wir nur die Methode setLabel() ändern, ohne anderen Code zu berühren.

Schritte zum Implementieren von Attributen

Wir wissen, dass beim Lesen und Schreiben einer nicht vorhandenen Mitgliedsvariablen eines Objekts automatisch __get() __set() aufgerufen wird. Yii macht sich dies zunutze, um Unterstützung für Attribute bereitzustellen. Aus dem obigen Code können Sie ersehen, dass Yii die Funktion mit dem Namen getpropertyname() aufruft, wenn Sie auf eine bestimmte Eigenschaft eines Objekts zugreifen. Beispielsweise ruft SomeObject->Foo automatisch SomeObject->getFoo() auf. Wenn eine Eigenschaft geändert wird, wird die entsprechende Setter-Funktion aufgerufen. Beispielsweise ruft SomeObject->Foo = $someValue automatisch SomeObject->setFoo($someValue) auf.

Daher sind zum Implementieren von Eigenschaften normalerweise drei Schritte erforderlich:

Erbt von yiibaseObject .

Deklarieren Sie eine private Mitgliedsvariable, die zum Speichern dieser Eigenschaft verwendet wird.

Bietet Getter- oder Setter-Funktionen oder beides für den Zugriff auf und die Änderung der oben genannten privaten Mitgliedsvariablen. Wenn nur der Getter bereitgestellt wird, ist die Eigenschaft schreibgeschützt, und wenn nur der Setter bereitgestellt wird, ist die Eigenschaft schreibgeschützt.

Die folgende Post-Klasse implementiert den lesbaren und beschreibbaren Attributtitel:

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 的读写的。但这不是好的习惯,理由如下:

失去了类的封装性。 一般而言,成员变量对外不可见是比较好的编程习惯。 从这里你也许没看出来,但是假如有一天,你不想让用户修改标题了,你怎么改? 怎么确保代码中没有直接修改标题? 如果提供了setter,只要把setter删掉,那么一旦有没清理干净的对标题的写入,就会抛出异常。 而使用 public $title 的方法的话,你改成 private $title 可以排查写入的异常,但是读取的也被禁止了。
对于标题的写入,你想去掉空格。 使用setter的方法,只需要像上面的代码段一样在这个地方调用 trim() 就可以了。 但如果使用 public $title 的方法,那么毫无疑问,每个写入语句都要调用 trim() 。 你能保证没有一处遗漏?
因此,使用 public $title 只是一时之快,看起来简单,但今后的修改是个麻烦事。 简直可以说是恶梦。这就是软件工程的意义所在,通过一定的方法,使代码易于维护、便于修改。 一时看着好像没必要,但实际上吃过亏的朋友或者被客户老板逼着修改上一个程序员写的代码,问候过他亲人的, 都会觉得这是十分必要的。

但是,世事无绝对。由于 __get() 和 __set() 是在遍历所有成员变量,找不到匹配的成员变量时才被调用。 因此,其效率天生地低于使用成员变量的形式。在一些表示数据结构、数据集合等简单情况下,且不需读写控制等, 可以考虑使用成员变量作为属性,这样可以提高一点效率。

另外一个提高效率的小技巧就是:使用 $pro = $object->getPro() 来代替 $pro = $object->pro , 用 $objcect->setPro($value) 来代替 $object->pro = $value 。 这在功能上是完全一样的效果,但是避免了使用 __get() 和 __set() ,相当于绕过了遍历的过程。

这里估计有人该骂我了,Yii好不容易实现了属性的机制,就是为了方便开发者, 结果我却在这里教大家怎么使用原始的方式,去提高所谓的效率。 嗯,确实,开发的便利性与执行高效率存在一定的矛盾。我个人的观点更倾向于以便利为先, 用好、用足Yii为我们创造的便利条件。至于效率的事情,更多的是框架自身需要注意的, 我们只要别写出格外2的代码就OK了。

不过你完全可以放心,在Yii的框架中,极少出现 $app->request 之类的代码,而是使用 $app->getRequest() 。 换句话说,框架自身还是格外地注重效率的,至于便利性,则留给了开发者。 总之,这里只是点出来有这么一个知识点,至于用不用,怎么用,完全取决于你了。

值得注意的是:

由于自动调用 __get() __set() 的时机仅仅发生在访问不存在的成员变量时。 因此,如果定义了成员变量 public $title 那么,就算定义了 getTitle() setTitle() , 他们也不会被调用。因为 $post->title 时,会直接指向该 pulic $title , __get() __set() 是不会被调用的。从根上就被切断了。
由于PHP对于类方法不区分大小写,即大小写不敏感, $post->getTitle() 和 $post->gettitle() 是调用相同的函数。 因此, $post->title 和 $post->Title 是同一个属性。即属性名也是不区分大小写的。
由于 __get() __set() 都是public的, 无论将 getTitle() setTitle() 声明为 public, private, protected, 都没有意义,外部同样都是可以访问。所以,所有的属性都是public的。
由于 __get() __set() 都不是static的,因此,没有办法使用static 的属性。
Object的其他与属性相关的方法

除了 __get() __set() 之外, yii\base\Object 还提供了以下方法便于使用属性:

__isset() 用于测试属性值是否不为 null ,在 isset($object->property) 时被自动调用。 注意该属性要有相应的getter。

__unset() 用于将属性值设为 null ,在 unset($object->property) 时被自动调用。 注意该属性要有相应的setter。

hasProperty() 用于测试是否有某个属性。即,定义了getter或setter。 如果 hasProperty() 的参数 $checkVars = true (默认为true), 那么只要具有同名的成员变量也认为具有该属性,如前面提到的 public $title 。

canGetProperty() 测试一个属性是否可读,参数 $checkVars 的意义同上。只要定义了getter,属性即可读。 同时,如果 $checkVars 为 true 。那么只要类定义了成员变量,不管是public, private 还是 protected, 都认为是可读。

canSetProperty() testet, ob eine Eigenschaft beschreibbar ist. Die Bedeutung des Parameters $checkVars ist dieselbe wie oben. Solange der Setter definiert ist, kann die Eigenschaft geschrieben werden. Gleichzeitig ist $checkVars true . Solange die Klasse Mitgliedsvariablen definiert, unabhängig davon, ob sie öffentlich, privat oder geschützt sind, gelten sie als beschreibbar.

Objekt und Komponente

yiibaseComponent erbt von yiibaseObject und verfügt daher auch über grundlegende Funktionen wie Eigenschaften.

Da Component jedoch auch Ereignisse und Verhalten einführt, erbt es nicht einfach die Eigenschaftsimplementierungsmethode von Object, sondern überlädt Funktionen wie __get() __set() basierend auf demselben Mechanismus. Was den Implementierungsmechanismus betrifft, sind sie jedoch gleich. Das Verständnis wird dadurch nicht beeinträchtigt.

Wie bereits erwähnt, ist Yii offiziell als komponentenbasiertes Framework positioniert. Das Konzept der sichtbaren Komponenten ist die Grundlage von Yii. Wenn Sie daran interessiert sind, den Quellcode oder die API-Dokumentation von Yii zu lesen, werden Sie feststellen, dass fast alle Kernklassen von Yii von yiibaseComponent abgeleitet (geerbt) sind.

In Yii1.1 gab es bereits eine Komponente, damals CComponent. Yii2 teilt CComponent in Yii1.1 in zwei Klassen auf: yiibaseObject und yiibaseComponent.

Unter diesen ist Object relativ leichtgewichtig und definiert die Eigenschaften der Klasse durch Getter und Setter. Die Komponente ist vom Objekt abgeleitet und unterstützt Ereignisse und Verhalten. Daher weist die Komponentenklasse drei wichtige Merkmale auf:

Eigenschaft

Ereignis

Verhalten

Glauben Sie oder ich habe diese drei Merkmale mehr oder weniger verstanden sind wichtige Einstiegspunkte für die Anreicherung und Erweiterung von Klassenfunktionen und die Änderung des Klassenverhaltens. Daher hat Component in Yii einen sehr hohen Stellenwert.

Component bietet zwar mehr Funktionen und Komfort, hat aber die beiden Funktionen Ereignis und Verhalten hinzugefügt, was die Entwicklung erleichtert, aber ein gewisses Maß an Effizienz opfert. Wenn Sie die beiden Funktionen Ereignis und Verhalten während der Entwicklung nicht verwenden müssen, z. B. eine Klasse, die einige Daten darstellt. Dann können Sie nicht von Component, sondern von Object erben. Ein typisches Anwendungsszenario ist die Verwendung von Object, wenn es einen vom Benutzer eingegebenen Datensatz darstellt. Und wenn Sie das Verhalten von Objekten und Ereignissen verarbeiten müssen, die auf die Verarbeitung reagieren können, besteht kein Zweifel daran, dass Component verwendet werden sollte. In puncto Effizienz ist Object näher an nativen PHP-Klassen. Daher sollte Object nach Möglichkeit zuerst verwendet werden.

Verwandte Empfehlungen:

Einführung in das Yii2.0-Framework und praktisches Video-Tutorial zur Projektentwicklung

Yii2 Chinesisches Handbuch

Erstellen Sie Ihr eigenes PHP-Framework von Grund auf

Das obige ist der detaillierte Inhalt vonEigenschaft im Yii-Framework von PHP. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn