singleton

Singleton

<?php
trait Singleton
{
    protected static $instance;
    final public static function getInstance()
    {
        return isset(static::$instance)
            ? static::$instance
            : static::$instance = new static;
    }
    final private function __construct() {
        $this->init();
    }
    protected function init() {}
    final private function __wakeup() {}
    final private function __clone() {}    
}

对象复制及__clone

赋值(实质是引用赋值)
class myclass {
    public $data;
}
$obj1 = new myclass();
$obj1->data = "aaa";
$obj2 = $obj1;
$obj2->data ="bbb";     //$obj1->data的值也会变成"bbb"

克隆(浅拷贝)
class myclass {
    public $data;
}
$obj1 = new myclass();
$obj1->data ="aaa";
$obj2 = clone $obj1;
$obj2->data ="bbb";     // $obj1->data的值仍然为"aaa"

引用
class myClass{
    public $data;
}
$sss ="aaa";
$obj1 = new myClass();
$obj1->data =&$sss;   //注意,这里是个reference!
$obj2 = clone $obj1;
$obj2->data="bbb";  //这时,$obj1->data的值变成了"bbb" 而不是"aaa"!

由于clone的shallow copy的特性,采用PHP中的 __clone方法 把浅拷贝转换为深拷贝
class testClass
{
 public $str_data;
 public $obj_data;

 public function __clone() {
   $this->obj_data = clone $this->obj_data;
}

$dateTimeObj = new DateTime("2014-07-05", new DateTimeZone("UTC"));

$obj1 = new testClass();
$obj1->str_data ="aaa";
$obj1->obj_data = $dateTimeObj;

$obj2 = clone $obj1;
var_dump($obj1);  // str_data:"aaa"  obj_data:"2014-07-05 00:00:00"
var_dump($obj2);  // str_data:"aaa"  obj_data:"2014-07-05 00:00:00"
$obj2->str_data ="bbb";
$obj2->obj_data->add(new DateInterval('P10D'));

var_dump($obj1);  // str_data:"aaa"  obj_data:"2014-07-05 00:00:00"
var_dump($obj2);  // str_data:"aaa"  obj_data:"2014-07-15 00:00:00"
var_dump($dateTimeObj);  //"2014-07-05 00:00:00"

序列化和反序列化构造对象

魔术方法__sleep:
用serialize() 函数实例化一个类的时候会检查类中是否存在一个魔术方法 __sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。
此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。如果该方法未返回任何内容,
则 NULL 被序列化,并产生一个 E_NOTICE 级别的错误。__sleep() 方法常用于提交未提交的数据,或类似的清理操作。
同时,如果有一些很大的对象,但不需要全部保存,这个功能就很好用。

魔术方法__wakeup:
与serialize()相反,unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,
预先准备对象需要的资源。__wakeup() 经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。

class user {
    public $name;
    public $id;
    function __construct() {    // 给id成员赋一个uniq id 
        $this->id = uniqid();
    }
    function __sleep() {       //此处不串行化id成员
        return(array('name'));
    } 
    function __wakeup() {
        $this->id = uniqid();
    }
}

$u = new user();
$u->name = "Leo"; 
$s = serialize($u); //serialize串行化对象u,此处不串行化id属性,id值被抛弃
$u2 = unserialize($s); //unserialize反串行化,id值被重新赋值