您的位置:首页 > 编程语言 > PHP开发

PHP类中的魔术方法学习笔记之__set() __get() 等

2012-09-29 10:19 447 查看
首先上来就贴个代码:

<?php
class Test {

private $a;

public function __set($key, $value) { //必须是两个参数,第一个是属性,第二个是设置属性的值。
$this->$key = $value;

//这里不明白为什么是$this->$key ??
一般不是这样写吗? $this->key ? 请看我下面的分解。
}

public function __get($key) { //一个参数,要获得的属性
return $this->$key;

}
}
$test = new Test();

$test->__set('a', '我是A'); //给属性a
设置一个值
echo $test->__get('a'); //打印a
输出 我是A

?>

你可以注意到,$key只是我们需要传进来的一个内部属性,不是我们真正需要的,如果$this->key这样就会编程$key这个属性的值了,而我们需要设置的是$this->a的值,所以这里就需要使用变量的变量了。

在实践中,往往内部属性的个数是不定的,你想到了什么解决办法?对,就是数组,PHP中数组的长度是不定的,所以我们就可以给他无限增加元素。如果是注册的页面,我们就可以灵活的获得和设置属性了。但是在实际运用中,我们知道传过来的值是不可靠的,我们得需要HTML转义,Mysql转义等等,所以我们可以写一个简单的回调函数,做数据验证的作用。

<?php
class Test {

public $values = array('name' => '名字', 'passwd' => '密码'); //提前规定私有属性只有name和passwd

public function __get($name){

if (isset($this->values[$name])) { //判断一下
return $this->values[$name];

} else {

echo '没有此属性!';

}
}

public function __set($name, $value){

if (isset($this->values[$name])) { //这里也判断一下
$this->values[$name] = $this->validate($value);

} else {

echo '没有此属性!';

}
}
private function validate($value){

return htmlspecialchars(addslashes($value));

//等等
}
}
$test = new Test();

$test->__set('name', '<a>我是name</a>'); //设置name
无输出
$test->__set('我也不知道这个是什么', '<a>看看是我的值是多少</a>'); //输出没有此属性!
echo $test->__get('name'); //输出 <a>我是a</a>

echo $test->__get('随便看看'); //输出没有此属性!
?>

我们来看看 __isset() 和 __unset() 。

其实__isset() 和 __unset() 与 __sleep()和__wakeup() 是有点像的,__isset() 和 __unset() 是在触发isset()和unset()函数前的回调函数。我们继续来做例子。

<?php
class Test {

public $a;

public function __construct($value) {

$this->a = $value;

}

public function __isset($name) {

echo "你小子偷看我??";

}

public function __unset($name) {

echo "你没权利宰了我!";

}
}
$test = new Test("我是a");

isset($test->a); //无任何输出
?>

执行上面的代码,结果无任何输出,但是刚才我说了,只要执行isset()就要执行__isset()这个回调函数的啊,回调函数里面输出 “你小子偷看我??” ,但是为什么结果却没有输出呢?难道是我说错了??我不能欺骗大家啊,所以我得给大家说清楚,不是我错了,也不是程序错了,是PHP的问题!

在PHP中关于 __isset() 和 __unset() 有个约定,就是当用 isset() 函数测试成员属性的时候,如果这个属性为public属性或者默认属性时,就不回调,当为protected或者private时就回调。我语言表达能力差,还是用代码表示吧。

<?php
class Test {

var $a; //这样就不输出
public $a; //这样也不输出

protected $a; //输出你小子偷看我??

private $a; //输出你小子偷看我??

public function __construct($value) {

$this->a = $value;

}

public function __isset($name) {

echo "你小子偷看我??";

return isset($this->a); //返回真是的信息
}

public function __unset($name) {

echo "你没权利宰了我!";

}
}
$test = new Test("我是a");

isset($test->a);

?>

下面有个例子,没事的时候可以研究一下,有个怪物类中有个属性是怪物的血,你不能想unset()就unset(),也就是说你不能等怪物的血没完了就使他死了

<?php
class Monster {

/**
* 怪物的属性表
*
* @var array

*/
private $state = array('hp' => 100, 'mp' => 100);

/**
* 打击怪物
*
* @access public

* @return void

*
*/
public function hit() {

$this->state['hp'] = $this->state['hp'] - rand(1, 10);

}

/**
* 设置怪物属性
*
* @param string $key

* @param integer $value

* @access public

* @return void

*/
public function __set($key, $value) {

if (isset($this->state[$key])) {

$this->state[$key] = $this->validate($value);

} else {

echo '没有此属性!';

}
}

/**
* 获得怪物属性
*
* @param string $key

* @access public

* @return integer

*/
public function __get($key) {

if (isset($this->state[$key])) {

return $this->state[$key];

} else {

echo '没有此属性!';

}
}

/**
* 验证设定怪物的血是否合法
*
* @param integer $value

* @access private

* @return void

*/
private function validate($value){

if (is_int($value) && $value > 0) {

return $value;

} else {

return 0;

}
}

/**
* 查看是否存在怪物的状态
*
* @param string $key

* @return boolean

*/
public function __isset($key) {

return isset($this->state[$key]);

}

/**
* 查看怪物的属性是否为0

*
* @param string $key

* @access public

* @return void

*/
public function __unset($key) {

if ($this->state[$key] > 0) {

echo '你没权利宰了我!';

} else {

unset($this->state[$key]);

echo '我死了!';

}
}
}

$monster = new Monster();

$monster->__set('hp', 100); //设定怪物的血和蓝
$monster->__set('mp', 100);

$monster->__set('血', 200); //输出没有此属性!
while (isset($monster->hp)) { //当怪物还存在的时候
$monster->hit(); //开始打怪
unset($monster->hp); //消灭怪物
echo $monster->__get('hp'); //输出怪物剩余血量当怪物死后输出没有此属性!
}

?>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐