魔术方法、对象串行化

魔术方法

__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()方法中一定要有一个字符串作为返回值,通常在此方法中返回的字符串是使用对象中多个属性值连接而成的。

<?php
header('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()方法的。

<?php
header('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.txt
O: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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值