1 关注者

属性

在 PHP 中,类成员变量也被称为属性。这些变量是类定义的一部分,用于表示类实例的状态(即,区分类的不同实例)。在实践中,你可能经常想以特殊的方式处理属性的读取或写入。例如,你可能希望在将字符串赋值给 label 属性时始终进行修剪。你可以使用以下代码来完成这项任务

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

上面代码的缺点是你必须在代码中的任何可能设置 label 属性的地方调用 trim()。如果将来 label 属性有了新的要求,例如第一个字母必须大写,你又必须修改所有赋值给 label 的代码。代码重复会导致错误,你应该尽可能避免这种做法。

为了解决这个问题,Yii 引入了名为 yii\base\BaseObject 的基类,它支持基于gettersetter 类方法来定义属性。如果类需要该功能,它应该继承自 yii\base\BaseObject 或者它的子类。

信息: Yii 框架中的几乎所有核心类都继承自 yii\base\BaseObject 或它的子类。这意味着,只要你看到核心类中的 getter 或 setter,你就可以像使用属性一样使用它。

getter 方法是名称以 get 开头的函数;setter 方法以 set 开头。getset 前缀后面的名称定义了属性的名称。例如,getter getLabel() 和/或 setter setLabel() 定义了一个名为 label 的属性,如以下代码所示

namespace app\components;

use yii\base\BaseObject;

class Foo extends BaseObject
{
    private $_label;

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

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

明确地说,getter 和 setter 方法创建了 label 属性,在这种情况下,该属性在内部引用了一个名为 _label 的私有属性。

通过 getter 和 setter 定义的属性可以像类成员变量一样使用。主要区别在于,当读取这样的属性时,会调用相应的 getter 方法;当给属性赋值时,会调用相应的 setter 方法。例如

// equivalent to $label = $object->getLabel();
$label = $object->label;

// equivalent to $object->setLabel('abc');
$object->label = 'abc';

通过 getter 定义而没有 setter 的属性是只读的。尝试给这样的属性赋值会导致 InvalidCallException。类似地,通过 setter 定义而没有 getter 的属性是只写的,尝试读取这样的属性也会导致异常。只写属性并不常见。

通过 getter 和 setter 定义的属性有一些特殊规则和限制

  • 这类属性的名称是不区分大小写的。例如,$object->label$object->Label 是相同的。这是因为 PHP 中的函数名是不区分大小写的。
  • 如果这类属性的名称与类成员变量相同,则后者优先级更高。例如,如果上面的 Foo 类有一个成员变量 label,则赋值 $object->label = 'abc' 会影响成员变量 label;该行不会调用 setLabel() setter 方法。
  • 这些属性不支持可见性。无论属性是 public、protected 还是 private,对定义的 getter 或 setter 方法都没有影响。
  • 属性只能由非静态 getter 和/或 setter 定义。静态方法不会以相同的方式处理。
  • 对 `property_exists()` 的正常调用无法确定魔术属性。你应该分别调用 canGetProperty()canSetProperty()

回到本指南开头描述的问题,现在不需要在每个 `label` 值被赋值的地方调用 `trim()`,`trim()` 只需要在 setter `setLabel()` 中被调用。如果新的需求需要在初始时将标签大写,则可以快速修改 `setLabel()` 方法,而无需触碰其他代码。这个更改将普遍影响对 `label` 的所有赋值。

发现错别字或您认为此页面需要改进?
在 GitHub 上编辑它 !