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

首先上来就贴个代码:

  1. <?php
  2. class Test {
  3.     private $a;
  4.  
  5.     public function __set($key, $value) {  //必须是两个参数,第一个是属性,第二个是设置属性的值。
  6.         $this->$key = $value;
  7.         //这里不明白为什么是$this->$key ?? 一般不是这样写吗? $this->key ? 请看我下面的分解。
  8.      }
  9.  
  10.     public function __get($key) {  //一个参数,要获得的属性
  11.         return $this->$key;
  12.      }
  13. }
  14. $test = new Test();
  15. $test->__set('a', '我是A');  //给属性a 设置一个值
  16. echo $test->__get('a');  //打印a    输出   我是A
  17. ?>

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

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

  1. <?php
  2. class Test {
  3.     public $values = array('name' => '名字', 'passwd' => '密码');  //提前规定私有属性只有namepasswd
  4.  
  5.     public function __get($name){
  6.         if (isset($this->values[$name])) {  //判断一下
  7.             return $this->values[$name];
  8.          } else {
  9.             echo '没有此属性!';
  10.          }
  11.      }
  12.  
  13.     public function __set($name, $value){
  14.         if (isset($this->values[$name])) {  //这里也判断一下
  15.             $this->values[$name] = $this->validate($value);
  16.          } else {
  17.             echo '没有此属性!';
  18.          }
  19.      }
  20.     private function validate($value){
  21.         return htmlspecialchars(addslashes($value));
  22.         //等等
  23.      }
  24. }
  25. $test = new Test();
  26. $test->__set('name', '<a>我是name</a>');  //设置name 无输出
  27. $test->__set('我也不知道这个是什么', '<a>看看是我的值是多少</a>');  //输出没有此属性!
  28. echo $test->__get('name');  //输出   &lt;a&gt;我是a&lt;/a&gt;
  29. echo $test->__get('随便看看');  //输出没有此属性!
  30. ?>

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

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

  1. <?php
  2. class Test {
  3.     public $a;
  4.  
  5.     public function __construct($value) {
  6.         $this->a = $value;
  7.      }
  8.  
  9.     public function __isset($name) {
  10.         echo "你小子偷看我??";
  11.      }
  12.  
  13.     public function __unset($name) {
  14.         echo "你没权利宰了我!";
  15.      }
  16. }
  17. $test = new Test("我是a");
  18. isset($test->a); //无任何输出
  19. ?>

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

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

  1. <?php
  2. class Test {
  3.     var $a;  //这样就不输出
  4.     public $a;  //这样也不输出
  5.  
  6.     protected $a;  //输出你小子偷看我??
  7.     private $a;  //输出你小子偷看我??
  8.  
  9.     public function __construct($value) {
  10.         $this->a = $value;
  11.      }
  12.  
  13.     public function __isset($name) {
  14.         echo "你小子偷看我??";
  15.         return isset($this->a);  //返回真是的信息
  16.      }
  17.  
  18.     public function __unset($name) {
  19.         echo "你没权利宰了我!";
  20.      }
  21. }
  22. $test = new Test("我是a");
  23. isset($test->a);
  24. ?>

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

  1. <?php
  2. class Monster {
  3.     /**
  4.       * 怪物的属性表
  5.       *
  6.       * @var array
  7.       */
  8.     private $state = array('hp' => 100, 'mp' => 100);
  9.  
  10.     /**
  11.       * 打击怪物
  12.       *
  13.       * @access public
  14.       * @return void
  15.       *
  16.       */
  17.     public function hit() {
  18.         $this->state['hp'] = $this->state['hp'] - rand(1, 10);
  19.      }
  20.  
  21.     /**
  22.       * 设置怪物属性
  23.       *
  24.       * @param string $key
  25.       * @param integer $value
  26.       * @access public
  27.       * @return void
  28.       */
  29.     public function __set($key, $value) {
  30.         if (isset($this->state[$key])) {
  31.             $this->state[$key] = $this->validate($value);
  32.          } else {
  33.             echo '没有此属性!';
  34.          }
  35.      }
  36.  
  37.     /**
  38.       * 获得怪物属性
  39.       *
  40.       * @param string $key
  41.       * @access public
  42.       * @return integer
  43.       */
  44.     public function __get($key) {
  45.         if (isset($this->state[$key])) {
  46.             return $this->state[$key];
  47.          } else {
  48.             echo '没有此属性!';
  49.          }
  50.      }
  51.  
  52.     /**
  53.       * 验证设定怪物的血是否合法
  54.       *
  55.       * @param integer $value
  56.       * @access private
  57.       * @return void
  58.       */
  59.     private function validate($value){
  60.         if (is_int($value) && $value > 0) {
  61.             return $value;
  62.          } else {
  63.             return 0;
  64.          }
  65.      }
  66.  
  67.     /**
  68.       * 查看是否存在怪物的状态
  69.       *
  70.       * @param string $key
  71.       * @return boolean
  72.       */
  73.     public function __isset($key) {
  74.         return isset($this->state[$key]);
  75.      }
  76.  
  77.     /**
  78.       * 查看怪物的属性是否为0
  79.       *
  80.       * @param string $key
  81.       * @access public
  82.       * @return void
  83.       */
  84.     public function __unset($key) {
  85.         if ($this->state[$key] > 0) {
  86.             echo '你没权利宰了我!';
  87.          } else {
  88.              unset($this->state[$key]);
  89.             echo '我死了!';
  90.          }
  91.      }
  92. }
  93.  
  94. $monster = new Monster();
  95. $monster->__set('hp', 100);  //设定怪物的血和蓝
  96. $monster->__set('mp', 100);
  97. $monster->__set('', 200);   //输出没有此属性!
  98. while (isset($monster->hp)) {  //当怪物还存在的时候
  99.     $monster->hit();           //开始打怪
  100.      unset($monster->hp);       //消灭怪物
  101.     echo $monster->__get('hp');  //输出怪物剩余血量当怪物死后输出没有此属性!
  102. }
?>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值