Maison  >  Article  >  développement back-end  >  Propriété dans le framework Yii de PHP

Propriété dans le framework Yii de PHP

小云云
小云云original
2017-11-13 11:50:281315parcourir

Yii est un framework PHP hautes performances basé sur des composants pour développer des applications Web à grande échelle. Yii est écrit en POO stricte et dispose de références de bibliothèque complètes et de didacticiels complets. De MVC, DAO/ActiveRecord, widgets, mise en cache, RBAC hiérarchique, services Web, jusqu'aux thèmes, I18N et L10N, Yii fournit presque tout ce dont vous avez besoin pour le développement d'applications Web 2.0 d'aujourd'hui. En fait, Yii est l’un des frameworks PHP les plus efficaces.

Yii est un framework de développement d'applications Web PHP5 hautes performances. Un simple outil de ligne de commande yiic peut créer rapidement un cadre de code d'application Web. Les développeurs peuvent ajouter une logique métier basée sur le cadre de code généré pour terminer rapidement le développement d'applications.

En PHP, les variables membres de la classe sont également appelées propriétés. Ils font partie de la définition de la classe et sont utilisés pour représenter l'état d'une instance (c'est-à-dire pour distinguer les différentes instances de la classe). Dans la pratique spécifique, nous souhaitons souvent utiliser une méthode un peu spéciale pour lire et écrire des attributs. Par exemple, si vous devez effectuer une opération de découpage sur l'attribut label à chaque fois, vous pouvez utiliser le code suivant pour y parvenir :

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

L'inconvénient du code ci-dessus est que tant que l'attribut label est modifié, la fonction trim() doit être rappelée. Si vous devez gérer l'attribut label d'une autre manière à l'avenir, par exemple en mettant la première lettre en majuscule, vous devrez modifier tout le code qui attribue des valeurs à l'attribut label. Cette duplication de code peut conduire à des bugs, et cette pratique doit évidemment être évitée autant que possible.

Pour résoudre ce problème, Yii introduit une classe de base appelée yiibaseObject, qui prend en charge la définition de propriétés basées sur les méthodes getter et setter (lecteur et setter) au sein de la classe. Si une classe doit prendre en charge cette fonctionnalité, elle doit uniquement hériter de yiibaseObject ou de ses sous-classes.

Supplément : presque toutes les classes principales du framework Yii héritent de yiibaseObject ou de ses sous-classes. Cela signifie que chaque fois que vous voyez une méthode getter ou setter dans une classe principale, vous pouvez l'appeler comme une propriété.
Les méthodes Getter sont des méthodes dont les noms commencent par get, tandis que les noms de méthodes setter commencent par set. La partie après get ou set dans le nom de la méthode définit le nom de la propriété. Comme le montre le code suivant, la méthode getter getLabel() et la méthode setter setLabel() opèrent sur l'attribut label :

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

(Explication détaillée : les méthodes getter et setter créent un attribut nommé label, Dans cet exemple, il pointe vers une propriété interne privée _label )

Les propriétés définies par les getters/setters sont utilisées de la même manière que les variables membres de la classe. La principale différence entre les deux est que lorsque cette propriété est lue, la méthode getter correspondante sera appelée et lorsqu'une valeur est attribuée à la propriété, la méthode setter correspondante sera appelée ; Par exemple :

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

Les propriétés qui définissent uniquement des getters et aucun setter sont des propriétés en lecture seule. Toute tentative d'attribution à une telle propriété entraînera une exception yiibaseInvalidCallException (appel invalide). De même, les propriétés définies avec uniquement des méthodes setter mais aucune méthode getter sont des propriétés en écriture seule, et les tentatives de lecture de ces propriétés déclencheront également une exception. Il n'existe pratiquement aucun cas d'utilisation d'attributs en écriture seule.

Les propriétés définies via les getters et les setters ont également des règles et restrictions spéciales :

Les noms de ces propriétés ne sont pas sensibles à la casse. Par exemple, $object->label et $object->Label sont la même propriété. Parce que les noms de méthodes PHP ne sont pas sensibles à la casse.
Si le nom de ce type d'attribut est le même que celui d'une variable membre de la classe, cette dernière prévaudra. Par exemple, supposons que la classe Foo ci-dessus ait une variable membre label, puis l'attribution d'une valeur à $object->label = 'abc' sera attribuée à la variable membre au lieu de la méthode setter setLabel().
Ce type de propriété ne prend pas en charge la visibilité (restrictions d'accès). Le fait que les méthodes getter et setter d'une propriété soient publiques, protégées ou privées n'a aucun effet sur la visibilité de la propriété.
Les méthodes getter et setter de ce type de propriété ne peuvent être définies que comme non statiques. Si elles sont définies comme méthodes statiques (static), elles ne seront pas traitées de la même manière.
Pour en revenir au problème évoqué au début, au lieu d'appeler la fonction trim() partout, il suffit désormais de l'appeler une seule fois dans la méthode setter setLabel(). Si une nouvelle exigence survient selon laquelle la première lettre de l'étiquette doit être en majuscule, il suffit de modifier la méthode setLabel() sans toucher à aucun autre code.

Étapes pour implémenter les attributs

Nous savons que lors de la lecture et de l'écriture d'une variable membre inexistante d'un objet, __get() __set() sera automatiquement appelé. Yii en profite pour prendre en charge les attributs. À partir du code ci-dessus, vous pouvez voir que si vous accédez à une propriété d'un objet, Yii appellera une fonction appelée getpropertyname(). Par exemple, SomeObject->Foo appellera automatiquement SomeObject->getFoo(). Si une propriété est modifiée, la fonction setter correspondante sera appelée. Par exemple, SomeObject->Foo = $someValue appellera automatiquement SomeObject->setFoo($someValue).

Par conséquent, pour implémenter les propriétés, il y a généralement trois étapes :

Hérite de yiibaseObject .

Déclarez une variable membre privée utilisée pour enregistrer cette propriété.

Fournit des fonctions getter ou setter, ou les deux, pour accéder et modifier les variables membres privées mentionnées ci-dessus. Si seul le getter est fourni, la propriété est en lecture seule, et si seul le setter est fourni, la propriété est en écriture seule.

La classe Post suivante implémente l'attribut titre lisible et inscriptible :

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() teste si une propriété est accessible en écriture. La signification du paramètre $checkVars est la même que ci-dessus. Tant que le setter est défini, la propriété peut être écrite. En même temps, $checkVars est true . Ensuite, tant que la classe définit des variables membres, qu'elles soient publiques, privées ou protégées, elles sont considérées comme accessibles en écriture.

Objet et composant

yiibaseComponent hérite de yiibaseObject, il possède donc également des fonctions de base telles que des propriétés.

Cependant, puisque Component introduit également des événements et des comportements, il n'hérite pas simplement de la méthode d'implémentation des propriétés d'Object, mais surcharge des fonctions telles que __get() __set() basées sur le même mécanisme. Mais en termes de mécanisme de mise en œuvre, ce sont les mêmes. Cela n’affecte pas la compréhension.

Comme mentionné précédemment, Yii se positionne officiellement comme un framework basé sur des composants. Le concept de composants visibles est le fondement de Yii. Si vous souhaitez lire le code source ou la documentation de l'API de Yii, vous constaterez que presque toutes les classes principales de Yii sont dérivées de (héritées de) yiibaseComponent.

Dans Yii1.1, il y avait déjà un composant, qui était à cette époque CComponent. Yii2 divise CComponent dans Yii1.1 en deux classes : yiibaseObject et yiibaseComponent.

Parmi eux, Object est relativement léger et définit les propriétés de la classe via des getters et des setters. Le composant est dérivé d'Object et prend en charge les événements et les comportements. La classe Component possède donc trois caractéristiques importantes :

propriété

événement

comportement

Croyez-vous ou moi avons plus ou moins compris que ces trois caractéristiques sont des points d’entrée importants pour enrichir et étendre les fonctions de classe et changer le comportement de classe. Par conséquent, Component a un statut très élevé dans Yii.

Tout en offrant plus de fonctions et de commodité, Component a ajouté les deux fonctionnalités d'événement et de comportement, ce qui facilite le développement tout en sacrifiant une certaine efficacité. Si vous n'avez pas besoin d'utiliser les deux fonctionnalités d'événement et de comportement pendant le développement, comme une classe qui représente certaines données. Ensuite, vous pouvez hériter d'un objet au lieu d'un composant. Un scénario d'application typique consiste à utiliser Object s'il représente un ensemble de données saisies par l'utilisateur. Et si vous avez besoin de gérer le comportement de l'objet et les événements qui peuvent répondre au traitement, il ne fait aucun doute que Component doit être utilisé. En termes d'efficacité, Object est plus proche de la classe PHP native, donc lorsque cela est possible, Object doit être utilisé en premier.

Recommandations associées :

Introduction au framework Yii2.0 et didacticiel vidéo pratique sur le développement de projets

Manuel chinois Yii2

Créez votre propre framework PHP à partir de zéro

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn