+ -
当前位置:首页 → 问答吧 → 魔术方法详解

魔术方法详解

时间:2008-11-05

来源:互联网

PHP5的OOP可以说是PHP5跟PHP4的最大变动。

而魔术方法可能是PHP的特色了。有了魔术方法,我们可以实现很多功能。今天我们来学习一下PHP5类中的魔术方法吧!!
PHP提供了很多魔术方法,我们一一说明怎么使用,魔术方法包括:__construct, __destruct , __call, __callStatic, __get, __set, __isset, __unset , __sleep, __wakeup, __toString, __set_state 和 __clone。


1.首先是 __sleep()和__wakeup()
__sleep()方法是在使用serialize()函数序列化一个对象时自动调用的,不是很明白吧。看例子:

<?php
class MyClass {
    private $name;
    public function __construct($name) {
        $this->name = $name
    }
    public function __sleep() {
        echo "我睡觉了...";
    }
}

$mc = new MyClass();
$mc = serialize($mc);
?>

输出:我睡觉了...

假如开启了E_NOTICE错误报告,就会看到以下错误:
Notice: serialize() [function.serialize]: __sleep should return an array only containing the names of instance-variables to serialize in D:\AppServ\www\test\magic.php on line 12

为什么呢?原来__sleep()方法调用时一定要返回一个数组,一般都是返回一个关于对象成员变量的数组,上面我们有一个名为name的成员变量,所以我们就要在__sleep()方法中返回array('name')这样的数字(为什么要返回这样的数组,我等下解释)。我们修改一下吧:

<?php
class MyClass {
    private $name;
    public function __construct($name) {
        $this->name = $name
    }
    public function __sleep() {
        echo "我睡觉了...";
        return array();
    }
}

$mc = new MyClass('Tony');
$mc = serialize($mc);
?>

运行后发现没有警告了,成功!

说完__sleep()方法就要说说__wakeup()方法了,其实__wakeup()方法跟__sleep()方法刚好相反,就是在使用unserialize()函数对对象反序列化时自动调用的。我们在上面的例子中添加__wakeup()方法,看例子:

<?php
class MyClass {
    private $name;
    public function __construct($name) {
        $this->name = $name
    }
    public function __sleep() {
        echo "我睡觉了...";
        return array();
    }
    public function __wakeup() {
        echo "我睡醒了...";
    }
}

$mc = new MyClass(‘Tony’);
$mc = serialize($mc);
$mc = unserialize($mc);
?>


输出:
我睡觉了...我睡醒了...

嗯,两个方法都说完了,现在解释一下为什么__sleep()方法要返回一个关于对象成员变量的数组吧,我们修改一下我们的类:

<?php
class MyClass {
    private $name;
    public function __construct($name) {
        $this->name = $name
    }
    public function __sleep() {
        //echo "我睡觉了...";
        return array();
    }
    public function __wakeup() {
        //echo "我睡醒了...";
    }
    public function getName() {
        return $this->name;
    }
}

$mc = new MyClass(‘Tony’);
echo $mc->getName();
$mc = serialize($mc);
$mc = unserialize($mc);
echo $mc->getName();
?>


输出:Tony
可以看出我们第二次执行$mc->getName()时,并没有放回我们设置的Tony,现在我们把__sleep()方法的返回值改一下,改为array('name'),再执行一次,我们可以看到第二次都返回了Tony,说明返回这样形式的数组是为了在序列化时保存已经设了值得成员变量的。再看一个有用的例子吧:

<?php
class Connection {
    protected $link;
    private $server, $username, $password, $db;
   
    public function __construct($server, $username, $password, $db)
    {
        $this->server = $server;
        $this->username = $username;
        $this->password = $password;
        $this->db = $db;
        $this->connect();
    }
   
    private function connect()
    {
        $this->link = mysql_connect($this->server, $this->username, $this->password);
        mysql_select_db($this->db, $this->link);
    }
   
    public function __sleep()
    {
        return array('server', 'username', 'password', 'db');
    }
   
    public function __wakeup()
    {
        $this->connect();
    }
}
?>

在这个例子中,我们可以序列化这个连接数据库的对象,而保持在一个文件中,下次再用的时候就反序列化就可以了,免去了连接过程和设置了!!!

好了今天说到这里,明天继续!!!

作者: liexusong   发布时间: 2008-11-05

讲解的不错。

不过我对最后一个例子的解释有些看法。wakeup是在你反序列化的时候调用的。所以 "免去了连接过程和设置了!!!"其实不是真正意义上的不跟mysql交互,只是不用自己调用conenct(),所以运用到这个上面意义不大。

作者: 0hudu   发布时间: 2008-11-05

作者: 0hudu   发布时间: 2008-11-17