PHP魔术方法总结

1、调用属性

1)、__get()、__set()

1:在php面向对象的编程中,总是把类的属性定义为private。但是,对属性的读取和赋值操作是非常频繁的,因此在PHP5中,预定义了两个函数“__get()”和“__set()”来获取和赋值其属性。

2:类似于java中的javabean的操作,使用的方法也类似,只是不需要像javabean中那样,对每个字段进行set和get的操作。只需要加上两个魔术方法即可。这两个方法不是默认存在的,需要手工添加到类中,像构造方法(__construct())一样,在类中添加了才会存在。

例:

【注】

1:调用类的私有属性和成员

2:__set()方法必须有两个参数,返回值可有可无

   __get()方法必须有一个参数,返回值可有可无。

2)、__isset()

1:__isset()方法是用来检测私有属性是否存在:

2:在外部直接用isset()方法检测类的私有属性是检测不到的,只有在类中加了魔术方法__isset(),才能在外部使用isset()方法检测到。

【注】:必须有一个参数,,返回值有

3)、__unset()

1:__unset()方法用来在类的外部删除类的私有属性

2:在外部直接使用 unset()方法也是不行的,因为是私有属性,所以也需要在类里面使用魔术方法__unset().

【注】:必须有一个参数,返回值无

2、调用方法

1)、__call()

1:为了避免要调用的方法不存在时产生错误,我们使用魔术方法__cal()来避免。

2:如果没有__call()魔术方法,直接在外面调没有定义的go()方法会报错。

__call()方法的存在,让外面不会因为没有定义的方法而抛出错误,程序会正常的执行下去。

【注】参数有2(未定义方法名,参数【可以是数组】)

2)、__callStatic()

有了__callStatic(),当发现调用的静态方法不存在时,会自动调用这个魔术方法。程序不会报错。

【注】参数有2(未定义方法名,参数【可以是数组】)

get_called_class()返回类名

3、__invoke()

把对象以函数的方式被调用的时候,invoke方法就会被自动调用

4、__toString()

当你想打印对象的时候,这个方法就会被自动调用。

参数:无,返回值:必须有。

5、__clone

1)、深拷贝与浅拷贝

对象复制存在两种形式:浅拷贝,深拷贝

浅拷贝:变量之间是地址传递的。地址上是一个值,大家共享这个值。

深拷贝:把变量值复制一份,然后再传递给另一个变量。变量之间是值传递的,

使用关键字clone ,就能完成深拷贝。而PHP默认的是浅拷贝

浅拷贝的例子:

深拷贝的例子:

因为浅拷贝是非常省内存的,所以PHP默认的是浅拷贝的。

2)、__clone()方法的使用

__clone()这个魔术方法会在使用clone关键字的时候自动调用。

 

【注】参数:无,返回值:不需要。

6、序列化

1)、serialize()与unserialize ()

serialize()把类实例化出的对象转化成字符串的过程返回字符串,此字符串包含了表示 value 的字节流,可以存储于任何地方。

unserialize ()还原已经序列化的对象。

3)、__sleep()

1:__sleep():过滤掉在对象串行化过程中不需要留下的成员属性

2:在程序执行前,serialize() 函数会首先检查是否存在一个魔术方法 __sleep.如果存在,__sleep()方法会先被调用, 然后才执行串行化(序列化)操作。

3:这个功能可以用于清理对象,并返回一个包含对象中所有变量名称的数组。如果该方法不返回任何内容,则NULL被序列化,导致 一个E_NOTICE错误。

<?php
class user {
    public $name;
    public $id;
    function __construct() {  
        $this->id = uniqid();
     //uniqid() 函数基于以微秒计的当前时间,生成一个唯一的 ID。
    }   
    function __sleep() { //返回需要序列化的成员属性。      
        return(array('name'));
    }

 } 
$u = new user(); 
$u->name = "Leo"; 

$s = serialize($u); //id属性被抛弃,只序列化name属性。
print_r($s); //O:4:"user":1:{s:4:"name";s:3:"Leo";}
?>

【注】当一个对象被串行化,PHP会调用__sleep方法(如果存在的话),如果没有__sleep方法,PHP将保存所有属性。

4)、__wakeup()

1:__wakeup():经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。

2:当反串行化一个User对象,__wakeup方法建立id属性的新值

<?php
class user {
    public $name;
    public $id;
    function __construct() {  
        $this->id = 2;
    }   
    function __sleep() { //返回需要序列化的成员属性。
    //抛弃了id属性,并非抛弃,只是存在另一块内存中,只有__wakeup()方法才可唤醒      
        return(array('name'));
    }

    function __wakeup() {
    //唤醒id 属性,并给id 重新赋值。	
        $this->id = 3;
    }
 } 
$u = new user(); 
$u->name = "Leo"; 

$s = serialize($u); //id属性被抛弃,只序列化name属性。
$u2 = unserialize($s); //unserialize反串行化,id值被重新赋值 

//对象u和u2有不同的id赋值 
print_r($s);
print_r($u2);
/*打印结果:
user Object ( [name] => Leo [id] => 2 ) user Object ( [name] => Leo [id] => 3 )

?>

【注】

1:在反串行化一个对象时,PHP 会调用__wakeup方法(如果存在)。

2:这两个方法都不接受参数. __sleep方法必须返回一个数组,包含需要串行化的属性. PHP会抛弃其它属性的值.

【问题】

1:当序列化时__sleep()方法没有出现时,反序列化时__wakeup()方法存在可以吗?有什么用?

答案:可以存在,__sleep()不存在,PHP默认的把所有属性都序列化保存。而在反序列化时__wakeup()存在,依然会先执行,进行赋值或初始化操作。

<?php
class A {
 public $b;
 public $name; 
} 
class B extends A {
	public $parent;
	public function __wakeup() {
	 	$this->parent->name;//给B的parent属性赋值为$name
	}
}
 
$a = new A();
$a->name = "foo";
$a->b = new B();

$s = serialize($a);

$m = unserialize($s);
var_dump($m);exit;	
/*因为反序列化时先执行 __wakeup(),而__wakeup()在B类中。
 所以在B::__wakeup执行时, $a->name还没有被赋值,所以为NULL
*/
//object(A)#3 (2) { ["b"]=> object(B)#4 (3) { ["parent"]=> NULL ["b"]=> NULL ["name"]=> NULL }  ["name"]=> string(3) "foo" }

//所以,一定要小心你定义类中变量的执行顺序。
?>

 

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值