[Yii2笔记]050属性(Properties) [ 技术分享 ]
说明
学习Yii Framework 2(易2框架)的过程是漫长的,也是充满乐趣的,以下是我学习Yii2框架时对官网英文资料(请参见原文网址)的翻译和代码实现,提供了较完整的代码,供你参考。不妥之处,请多多指正!
原文网址:
http://www.yiiframework.com/doc-2.0/guide-concept-properties.html
本文主题:属性(Properties)
在PHP中,类成员变量被称作属性(property),这些变量是类定义的一部分,用于代表类实例的状态(换言之,用于区分类的另一个实例)。在实际应用中,我们常常想要通过一些特殊方法去读取或修改属性值,例如:要把一个字符串赋给label属性时,你可能会去掉它的首尾空格,使用以下代码即可完成:
$object->label=trim($label);
上句代码的缺点是,在你需要设置label属性的地方,你都必须调用trim() 函数,假如,某一天label属性有了一个新需求,要把首字母都变成大写,你可能需要发动label相关的每一处代码。重复修改代码就象平时练习一样难以避免,而且还会产生一些bug。
为了解决这个问题,Yii引入了一个基类:yii\base\Object,它可以使用类方法getter和setter来定义属性,如果一个类需要这些方法,它可以继承yii\base\Object或它的子类即可:
提示:几乎所有的Yii框架核心类都继承自yii\base\Objects或它的子类,也就是说,在一个核心类中无论你是否看到了setter或getter方法,你都可以象一个属性一样使用它。
getter方法是一个名称由get开始的方法;setter方法是由set开始的方法。get或set之后是属性的名称,例如:一个名为getLabel()的getter方法和一个名setLabel()的setter方法定义了一个名为label的属性,定义代码如下:
namespace app\components;
use yii\base\Object;
class Foo extends 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->label;
//等同于调用:
$label=$object->getLabel();
$object->label='abc';
//等同于调用:
$object->setLabel('abc');
当一个属性仅定义了getter而没有定义setter时是只读属性(read only),试图向它赋值会产生InvalidCallException 的异常;类似的一个属性只定义了setter而没有定义getter是只写属性(write-only),尝试云读取此属性也会产生异常,当然,只写属性并不常用。
属性使用getter和setter定义时会有一些特殊的规则和限制: 1、属性是不区分大小写的,例如:$object->label和$object->Label是相同的,这是因为在PHP中方法名是不区分大小写的。 2、如果属性名与类成员变量重名,则仅类成员变量有效,例如,如果Foo类中有一个成员变量名为label,$object->label='abc'赋值,将会影响成员变量label,而并不会调用setLabel()方法。 3、这些属性不支持可见性,也就是说getter或setter方法设置的属性没有public、protected或private的区别。 4、属性只能被非静态(non-static)的getter和setter方法定义,静态方法将不会按此方式处理。 5、调用property_exists()方法无法判断此种属性的存在与否,因为此种属性是通过魔术方法创建的,可以使用canGetProperty()或canSetProperty()方法来实现判断,hasProperty()。
回到前述的问题,不用到处修改label值去添加trim()方法,只需要在setLabel()添加一处trim()即可,当一个新需要要将label的首字母大小时,setLabel()方法可以被很快的修改而无需修改其他的代码,此处的变化将影响到所有使用label的地方。
实例1:getter、setter应用实例:
D:\phpwork\advanced\frontend\controllers\PostController.php
public function actionLabel(){
$object=new \frontend\models\Label();
$object->label=' abc11 ';
// $object->Label=' abc11 ';//与上句等效,不区分大小写
echo "<br>label:".$object->label;
// echo "<br>label:".$object->Label;//与上句等效,不区分大小写
$object->setlabel(' abc23 ');
// $object->setLabel(' abc23 ');//与上句等效,不区分大小写
echo "<br>label:".$object->getlabel();
// echo "<br>label:".$object->getLabel();//与上句等效,不区分大小写
}
测试结果:
/*
label:abc11
label:abc23
*/
D:\phpwork\advanced\frontend\models\Label.php
<?php
namespace frontend\models;
use Yii;
use yii\base\Object;
class Label extends Object{
private $_label;
public function getLabel(){
return $this->_label;
}
public function setLabel($value){
$this->_label=trim($value);
}
}
实例2:属性是否存在的判断方法canGetProperty()
D:\phpwork\advanced\frontend\controllers\PostController.php
public function actionLabel(){
$object=new \frontend\models\Label();
$have=property_exists($object,'name');
echo "<br>have name(var):".var_export($have,true);
$have=property_exists($object,'label');
echo "<br>have label(var):".var_export($have,true);
$have=$object->canGetProperty('name');
echo "<br>have name(var):".var_export($have,true);
$have=$object->canGetProperty('name',false);
echo "<br>have name(property):".var_export($have,true);
$have=$object->canGetProperty('label');
echo "<br>have label(property):".var_export($have,true);
}
测试结果:
/*
have name(var):true
have label(var):false
have name(var):true
have name(property):false
have label(property):true
*/
D:\phpwork\advanced\frontend\models\Label.php
<?php
namespace frontend\models;
use Yii;
use yii\base\Object;
class Label extends Object{
public $name;
private $_label;
public function getLabel(){
return $this->_label;
}
public function setLabel($value){
$this->_label=trim($value);
}
}
(全文完)
共 0 条回复
阿江
最后登录:2024-03-03
在线时长:186小时21分
- 粉丝94
- 金钱16816
- 威望160
- 积分20276