Discuz教程网

PHP 魔术函数使用说明

[复制链接]
authicon dly 发表于 2011-9-6 11:17:45 | 显示全部楼层 |阅读模式
什么是魔术函数?
对于__开头的函数就命名为魔术函数, 此类函数都在特定的条件下触发的.比如: __set() __get()等
在设置或取不存在的属性时候触发.
有那些魔术函数呢?
总的来说, 有下面几个魔术函数
__construct() __destruct() __get() __set() __isset() __unset() __call() __callStatic()
__sleep() __wakeup() __toString() __set_state() __clone() __autoload()
__construct()当实例化一个对象的时候,这个对象的这个方法首先被调用。
__destruct()当删除一个对象或对象操作终止的时候,调用该方法。
代码如下:

  1. class test1 {
  2. public function __construct() {
  3. var_dump(__function__);
  4. }
  5. public function __destruct() {
  6. var_dump(__function__);
  7. }
  8. }
  9. $t1 = new test1 ;
  10. unset($t1);
复制代码


__get当试图读取一个并不存在的属性的时候被调用。
__set当试图向一个并不存在的属性写入值的时候被调用。
__isset当试图检测一个并不存在的属性时候被调用。
__unset当试图取消一个并不存在的属性时候被调用。
代码如下:

  1. class test2 {
  2. public $name3;
  3. public function __set($key, $value) {
  4. var_dump(__function__. '
  5. KEY:'
  6. .$key.'
  7. Value:'
  8. .$value);
  9. }
  10. public function __get($key) {
  11. var_dump(__function__. 'KEY:'.$key);
  12. }
  13. public function __isset($key) {
  14. var_dump(__function__. ' KEY:'.$key);
  15. }
  16. public function __unset($key) {
  17. var_dump(__function__. ' KEY:'.$key);
  18. }
  19. }
  20. $t =new test2 ;
  21. $t->name = "steven";
  22. $t->name2;
  23. $t->name3;
  24. isset($t->name2);
  25. isset($t->name3);
  26. unset($t->name4);
复制代码


__sleep当进行序列化对象时候调用
__wakeup当进行反序列对象时候调用
需要注意一点:
1. __sleep()必须返回一个数组或者对象(一般返回的是$this),返回的值将会被用来做为序列化的
值。
如果不返回这个值,则序列化失败。这也意味着反序列化将不会触发__wakeup事件。
2. 序列化会保存默认赋值的属性.如果要通过实例化赋值的内容,则需要属性在__sleep()返回数组的
指定.
如$id与$id2的区别.
代码如下:

  1. class test3 {
  2. public $name = "steven";
  3. public $id = "1"; public $id2;
  4. public function __sleep() {
  5. var_dump(__function__); // 序列化不成功.没有返回值.反序列也失败 //
  6. return array("name"); // 序列化成功.有返回值.反序列成功.id2属性能被恢复 //
  7. return array("name", "id2");// 序列化成功.有返回值.反序列成功.id2属性不能被恢复
  8. return array("name"); }
  9. public function testEcho() {
  10. var_dump($this->name);
  11. var_dump($this->id);
  12. var_dump($this->id2);
  13. }
  14. public function __wakeup() {
  15. var_dump(__function__);
  16. $this->testEcho();
  17. }
  18. }
  19. $t3= new test3 ;
  20. $t3->id2 = uniqid();
  21. $t3s = serialize($t3);
  22. unserialize($t3s);
复制代码


__toString当直接打印一个对象的时候,这个方法将会被调用
代码如下:

  1. class test4 {
  2. public function __toString() {
  3. return "toString";
  4. }
  5. }
  6. $t4 = new test4();
  7. echo $t4;
  8. print $t4;
  9. var_dump($t4);
  10. print_r($t4);
复制代码


__call($func, $param) 当尝试调用一个不存在的方法的时候被调用.
这个方法必须有两个参数,第一个为调用的方法名,第二个是一个被调用方法的参数数组。
需要注意的是,当你在一个子类调用父类的private的方法,或者在实例里调用类的非protect方法的
时候,并不会调用__call()
代码如下:

  1. class test5 {
  2. public function __call($func, $param) {
  3. var_dump('Function:'.$func);
  4. var_dump($param);
  5. }
  6. }
  7. $t5 = new test5;
  8. $t5->echoTest('xx','xx','xx');
复制代码


__callStatic()当尝试调用一个不存在的静态方法的时候被调用
这个方法必须有两个参数,第一个为调用的方法名,第二个是一个被调用方法的参数数组。
在PHP5.3中出现
代码如下:

  1. class test51 {
  2. public function __callStatic($fun, $param) {
  3. var_dump('Function:'.$func);
  4. var_dump($param);
  5. }
  6. }
  7. test51::test('xx','xx','xx');
复制代码


__set_state()当用var_export导出实例的时候被调用.此方法有一个参数,为包含所导出的实例的所
有成员属性的一个数组
代码如下:

  1. class test6 {
  2. public function __set_state($arr){
  3. var_dump($arr);
  4. }
  5. }
  6. $t6 = new test6;
  7. $t6->age = "12";
  8. var_export($t6, true);
  9. var_export($t6);
  10. eval('
  11. $b='
  12. .var_export($t6,true).';');
  13. print_r($b);
复制代码



__clone()当克隆实例时候被调用.
注意:
1.在php5里,对象间的赋值总是以地址引用来传递的.
2.如果要以实际值来传递,则需要用到clone关键词
3.clone的只是实例。如果实例中的某个成员属性也是个实例,那么这个成员属性还是会以引用方法被
传递到新的实例。
// 对象间的赋值总是以地址引用来传递的. $t71 $t72的age属性是一样的.
代码如下:

  1. class test71 {
  2. public $age = 10;
  3. }
  4. $t71 = new test71();
  5. $t72 = $t71 ;
  6. var_dump($t71->age) ;
  7. $t71->age =12 ;
  8. var_dump($t71->age) ;
  9. var_dump($t72->age) ; // 如果要以实际值来传递,则需要用到clone关键词 $t73 = clone $t71; $t71->age = 13 ; var_dump($t71->age) ;
  10. var_dump($t73->age) ; // 如果实例中的某个成员属性也是个实例,那么这个成员属性还是会以引用方法被传递到新的实例。
复制代码



代码如下:

  1. class test74 {
  2. public $age = 10;
  3. public $sub = null;
  4. }
  5. class test75 {
  6. public $age = 11;
  7. }
  8. $i = new test74;
  9. $i->sub = new test75();
  10. $i1 =clone $i;
  11. var_dump($i1->sub->age);
  12. $i->sub->age = 12;
  13. var_dump($i1->sub->age);
复制代码



// $i 和$i1虽然不是指向同一个实例,但是它们的成员属性$sub却是指向同一个实例。这时候,我们必须借
助__clone这个方法来对$sub进行复制。 // $i2和$3指向不同实例.成员属性$sub也指向不同实例.
代码如下:

  1. class test76 {
  2. public $age = 10;
  3. public $sub = null;
  4. public function __clone() {
  5. $this->sub = clone $this->sub;
  6. }
  7. }
  8. $i2 = new test76();
  9. $i2->sub = new test75();
  10. $i3 = clone $i2;
  11. $i2->sub->age = 15 ;
  12. var_dump($i3->sub->age);
复制代码



__autoload()函数.当创建一个实例化的时候,如果对应的类不存在,则会被调用
代码如下:

  1. function __autoload($class) {
  2.    if ( $class == "test8" ){
  3. require_once dirname(__FILE__).'/class8.php';
  4. }
  5. }
  6. spl_autoload();
  7. $t8 = new test8;
  8. var_dump($t8->age);
复制代码







上一篇:Apache环境下PHP利用HTTP缓存协议原理解析及应用分析
下一篇:PHP 静态变量与自定义常量的使用方法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1314学习网 ( 浙ICP备10214163号 )

GMT+8, 2025-5-2 18:43

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表