在PHP里,类的成员变量也被称之为属性,这些变量是类定义的一部分,被用来表示类实例的状态(区分不同类实例)。在具体的实践中,你可能要经常处理可读或者可写属性的特殊方式,举个例子, 你可能想要给属性$label赋值一个字符串,但是这个字符串必须使用trim函数过滤开头结尾的空格,为了完成这个特殊处理你可能需要使用如下代码
$object->label = trim($label);
上述代码的缺点是,凡是在给label属性赋值的时候,你都必须使用trim函数去处理。假设在以后label属性的首字母必须大写,那么凡是给label属性赋值的代码,就必须被修改。你应该尽可能的避免这种代码重复。
为了解决这个问题,yii引入了一个基础类[yii\base\Object],此类可以基于类的getter和setter方法来定义类属性。如果一个类需要以这种方式定义属性,继承[yii\base\Object]或者[yii\base\Object]的子类
提示:几乎所有yii2框架的核心类都继承了[yii\base\Object]类或者它的子类,这意味着核心类的getter或者setter方法你都可以以属性的方式使用
getter方法一get为前缀;setter方法以set为前缀,get或者set后面跟随属性的名称。举个例子,getLabel()和setLabel()定义了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);
}
}
(需要指出的是,getter和setter方法创建了一个label属性,在上述代码中实际上关联的是私有属性$_label)
有getter和setter方法定义的属性,可以被当作类的属性(成员变量)直接使用。不同之处在于,当属性被读时,关联的getter方法被调用,当属性被修改时,关联的setter方法被调用。例如:
// 等价于 $label = $object->getLabel();
$label = $object->label;
// 等价于 $object->setLabel('abc');
$object->label = 'abc';
一个由getter方法定义的属性,如果没有setter方法,那么此属性只读,尝试给该属性赋值的行为都会抛出一个[[yii\base\InvalidCallException|InvalidCallException]]异常。同样,假设定义了setter方法的属性没有getter方法,此属性只写,尝试读取只写属性的值也会抛出一个异常,只写属性不常见。
通过getter,setter方法定义的属性有几个特殊的规则和限制
- 此类属性大小写不敏感。比如:$object->label 和 $object->Label 是相同的,
- 使用getter,setter定义的属性如果在类中同时拥有同名的成员变量,同名的成员变量将会被优先使用。比如: Foo类有一个成员变量label,$foo->label = "test" 将会直接给label赋值,而不会调用setLabel()方法
- 此类属性不支持可见度。即无论属性的getter或者setter方法定义为public,protected,private,都没有区别
- 此类属性只能有非静态的getter,setter方法来定义,静态方法不会以相同的方式来处理
回到开头的问题,假设需要给label属性赋值,且要对值处理,替代在所有赋值代码处处理,而是在setter方法里处理所要赋予属性的值,当有任何新的需求或者规则施加在属性上时,只需要修改getter或者setter方法。修改一处,所以地方都生效。
好评!