魔术方法、对象串行化

来源:互联网 发布:学校机房还原软件 编辑:程序博客网 时间:2024/06/04 19:33

魔术方法

__clone()

php5中的对象模型是通过引用来调用对象的,但有时需要建立副本,改变原来对象时不希望影响到副本。在php 中可以使用对象克隆出一个完全一样的对象,克隆后,原本和克隆副本两个对象完全独立,互不干扰。使用clone关键字实现.

<?php header('content-type:text/html;charset=utf-8');class Person{    var $name;    var $sex;    var $age;    function __construct($name,$sex="男",$age=1){        $this->name=$name;        $this->sex=$sex;        $this->age=$age;    }    function say(){        echo "我的姓名:".$this->name. " 性别:".$this->sex. ' 年龄:'.$this->age.'<br/>';    }}$p1=new Person('张三');$p2=clone $p1;//克隆副本$p1->say();$p2->say();//结果如下我的姓名:张三 性别:男 年龄:1我的姓名:张三 性别:男 年龄:1

上面通过clone关键克隆出来的一个完全一样的副本,两个对象完全独立。如果需要对克隆出来后的副本赋初值,可以在类中声明一个魔术方法“__clone”。该方法是在对象克隆时自动调用的,所以可以通过该方法对克隆后的副本赋初始值。该方法中自动包含$this和$that两个对象引用。其中$this表示对副本对象的引用,$that表示对原本对象的引用。

<?php header('content-type:text/html;charset=utf-8');class Person{    var $name;    var $sex;    var $age;    function __construct($name,$sex="男",$age=20){        $this->name=$name;        $this->sex=$sex;        $this->age=$age;    }    function __clone(){        $this->name="我是".$this->name."副本";        $this->age=10;    }    function say(){        echo "我的姓名:".$this->name. " 性别:".$this->sex. ' 年龄:'.$this->age.'<br/>';    }}$p1=new Person('张三');$p2=clone $p1;//自动调用__clone方法为副本赋初始值$p1->say();$p2->say();//结果如下:我的姓名:张三 性别:男 年龄:20我的姓名:我是张三副本 性别:男 年龄:10

_tostring()

魔法方法__tostring()是快速获取对象的字符串表示的最快捷的方法,它是直接输入对象的引用时直接调用的方法。例如:$p=new Person 对象的引用,如果直接使用echo 输出$p,则会出错。如果在类中添加__tostring()方法,则直接输入对象的引用时不会出错,而是自动调用该方法,并输出方法中返回的字符串。所以在__tostring()方法中一定要有一个字符串作为返回值,通常在此方法中返回的字符串是使用对象中多个属性值连接而成的。

<?phpheader('content-type:text/html;charset=utf-8');class Myclass{    private $foo;    private $x;    function __construct($foo,$head){        $this->foo=$foo;        $this->head=$head;    }    function __tostring(){       //该方法必须有一个字符串作为返回值         return $this->foo." ".$this->head;    }}$obj=new Myclass("Hello",'world!');echo $obj;//输入对象引用时自动调用__tostring()方法//结果如下:Hello world!

__call()

如果调用对象中不存在的方法,一定会出现系统错误,并退出程序不能继续执行。在php中,可以在类中添加一个魔法方法__call(),则调用对象中不存在的方法时就会自动调用该方法,并且程序会继续向下执行。所以我们可以接__call()方法提示用户,列如:提示该用户该方法不存在或者参数列表不存在。__call()方法需要两个参数,第一个参数是:调用不存在的方法时,接收这个方法名称的字符串,第二个参数是:参数列表则以数组的形式传递到__call()方法的。

<?phpheader('content-type:text/html;charset=utf-8');class Myclass{    function printfHello(){        echo "Hello";    }    function __call($functionName,$args){        echo "你所调用的函数".$functionName."(参数:";        print_r($args);        echo ")不存在<br/>";    }}$obj=new Myclass("Hello",'world!');//当函数不存在时,自动调用__call()方法,并把方法名和参数列表传给该函数$obj->myFun("one",2,"tree");$obj->otherFun(8,9);$obj->printfHello();//结果如下:你所调用的函数myFun(参数:Array ( [0] => one [1] => 2 [2] => tree ) )不存在你所调用的函数otherFun(参数:Array ( [0] => 8 [1] => 9 ) )不存在Hello

__autoload()

在面向对象中,如果我们使用一个未定义的类时,PHP会报一个致命的错误、一般我们用include包含一个类所在的源文件,如果一个页面需要使用多个类,就不得不在脚本页面开头编写一个长长的包含文件的列表,将本页面需要的类全部包含进来。这样处理不仅繁琐,而且容易出错。
PHP 中提供了类的自动加载功能,当你尝试使用一个PHP没有组织类的时,它会寻找一个__autoload()全局函数(不是在类中声明的函数),如果存在这个函数,PHP会用一个参数来调用它,参数即类名。

<?php   function __autoload($className){       //在方法中使用include包含类所在的文件        include(strtolower($className).".class.php");    }$p1=new Test();//Test类不存在则会自动调用__autoload()函数,将类名作为参数传入。

对象串行化

对象也是一种在内存中存储的数据类型,它的寿命通常随着生成该对象的程序的终止而终止。有时候,可能需要将对象的状态保存下来,需要的时候在恢复。对象通过描述自己状态的数值来记录自己,这个过程称对象的序列化。串行化就是把整个对象转化成二进制字符串。以下两种情况必须把对象串行化:
一:对象需要在网络中传输时,将对象串行化成二进制后再网络中传输。
二:对象需要持久保存时,将对象串行化写入文件或数据库中。
使用serialize()函数来串行化一个对象,把对象转化成二进制。serialize()函数需要一个参数就是对象的引用名,返回值为一个对象被串行化的字符串。
使用unserialize()函数来反串行化一个对象,就是把对象串行化后的二进制字符串在转化为对象。该函数的参数serialize()函数的返回值,返回值当然是重新组织好的对象。

Person.class.php

<?php header('content-type:text/html;charset=utf-8');class Person{    var $name;    var $sex;    var $age;    function __construct($name,$sex="男",$age=20){        $this->name=$name;        $this->sex=$sex;        $this->age=$age;    }    function say(){        echo "我的姓名:".$this->name. " 性别:".$this->sex. ' 年龄:'.$this->age.'<br/>';    } }

serialize.php

<?php header('content-type:text/html;charset=utf-8');require "Person.class.php";$person=new Person('张三','男',40);$person_string=serialize($person);file_put_contents("file.txt",$person_string);//file.txtO:6:"Person":3:{s:4:"name";s:6:"张三";s:3:"sex";s:3:"男";s:3:"age";i:40;}

unserialize.php

<?php header('content-type:text/html;charset=utf-8');require "Person.class.php";$person_string=file_get_contents("file.txt");$person=unserialize($person_string);$person->say();//结果如下:我的姓名:张三 性别:男 年龄:40

在php5中还提供两个魔术方法 __sleep()和__wakeup()可以使用。在调用serialize()函数将对象串行化时,会自动调用__sleep()方法,用来将对象中的部分成员串行化。__sleep()函数不需要接受任何参数,但需要返回一个数组,在数组中包含需要串行化的属性。未被包含在数组中的属性将在串行化时被忽略。如果类中没有该方法,则对象中的所有属性都将被串行化。在调用unserialize()函数反串行化时,会自动调用__wakeup()方法,用来二进制串中重新组成一个对象时,为新对象中的成员属性重新初始化。

<?php header('content-type:text/html;charset=utf-8');class Person{    var $name;    var $sex;    var $age;    function __construct($name,$sex="男",$age=20){        $this->name=$name;        $this->sex=$sex;        $this->age=$age;    }    function say(){        echo "我的姓名:".$this->name. " 性别:".$this->sex. ' 年龄:'.$this->age.'<br/>';    }     function __sleep(){        $arr=array("name","age");        return $arr;    }    function __wakeup(){        $this->age=40;    }}$person=new Person("张三");$person_string=serialize($person);echo $person_string."<br>";$person2=unserialize($person_string);$person2->say();//说明:其中成员属性$sex没有在数组中,没有被串行化,所有在反串行化时,组织成的对象将不会存在成员属性$sex//结果如下:O:6:"Person":2:{s:4:"name";s:6:"张三";s:3:"age";i:20;}我的姓名:张三 性别: 年龄:40
0 0
原创粉丝点击