

系统调用的,不是你自己调用的,你只要把这个方法写出来之后在特定的时机系统就会为你自动调用,你只需要实现这个方法即可。
__get
触发时机:对象在外部访问私有成员或者受保护属性时调用
该方法有一个参数:参数就是属性名
<?phpclass Person{public $name='小明';protected $age=18;private $height=187;//当你在外部试图通过对象来访问受保护的或者私有的成员属性时,就会自动触发__get()public function __get($name)//参数是属性名{if($name='age'){return $this->age;}//echo '$name';}}$niu=new Person();//echo $niu->age;//在类的外部通过对象,你只能访问公共的属性,不能访问受保护和私有的
__set
触发时机: 对象在外部设置私有或者受保护成员属性值的时候调用(get是获取的时候调用,set是设置的时候调用)
该方法有两个参数:
参数1:成员属性名
参数2:要设置的值
<?phpclass Person{public $name='小明';protected $age=18;private $height=187;//当你在外部试图通过对象来访问受保护的或者私有的成员属性时,就会自动触发__get()public function __get($name)//参数是属性名{if($name='age'){return $this->age;}//echo '$name';}public function __set($name,$value){//var_dump($name,$age)if($name=='age'){$this->age=$value;}}}$niu=new Person();//echo $niu->age;//在类的外部通过对象,你只能访问公共的属性,不能访问受保护和私有的//在外面我们去设置它私有或者受保护的属性$niu->age=20;
外部可以通过unset销毁对象中的public属性(那么针对私有的或者受保护的你能不能销毁呢?)
__unset
unset可以销毁一个变量,isset可以判断这个变量有没有被设置过值。
触发时机:对象在外部销毁私有或者受保护成员属性的时候调用
该方法有一个参数:参数就是私有的成员属性名
<?phpclass Person{public $name;protected $age;private $height;public function __unset($name) //有一个参数,就是你要销毁的属性名{if($name=='age'){unset($this->$name;)}}}$niu=new Person();//unset($niu->$name);//在类的外部我们可以通过unset来销毁类的公共属性unset($niu->$age);//会报错,自动触发__unset方法var_dump($niu);
__isset
触发时机:对象在外部判断私有或者受保护成员属性的时候调用
该方法有一个参数:参数就是私有的成员属性名
<?phpclass Person{public $name;protected $age;private $height;public function __unset($name) //有一个参数,就是你要销毁的属性名{if($name=='age'){unset($this->$name);}}public function __set($name,$value){if($name=='age'){$this->$name=$value;}}public function __get($name){if($name=='age'){return $this->$name;}}public function __isset($name){//在判断私有属性有没有被设置的时候就会自动的触发这个方法if($name=='age'){return isset($this->$name);}}$niu=new Person();//unset($niu->$name);//在类的外部我们可以通过unset来销毁类的公共属性//unset($niu->$age);//会报错,自动触发__unset方法//$niu->$age=100;// var_dump(isset($niu->age));
__construct:构造方法
触发时机:在创建对象的时候自动调用
这里我们经常做一些有关对象属性初始化的操作
__destruct: 析构方法
触发时机:在销毁对象的时候自动调用
脚本运行结束后$niu所占用的内存空间释放,释放的时候就是对象被销毁的时候,自动调用析构方法
代码总结:
<?php//__get: 对象在外部访问私有成员属性或者保护属性的时候调用//__set:对象在外部设置私有属性或者保护成员属性值的时候调用//__unset:对象在外部销毁私有或者受把傲虎的成员属性的时候调用//__isset:对象在外部判断私有或者受保护成员属性的时候调用//__construct:在创建对象的时候自动调用//__destruct:在销毁对象的时候自动调用class Person{public $name='小明';protected $age=18;private $height=178;public function __get($name){//echo '对象在外部访问私有成员属性或者保护属性的时候调用我';if($name=='age'){return $this->$name;}}public function __set($name,$value){//echo '对象在外部设置私有属性或者保护成员属性值的时候调用';if($name=='age'){$this->$name=$value;}}public function __unset($name){//echo '对象在外部销毁私有或者受把销毁的成员属性的时候调用';if($name='age'){unset($this->$name);}}public function __isset($name){//echo '对象在外部判断私有或者受保护成员属性的时候调用';if($name='age'){return isset($this->$name);}}public function __construct(){echo '在创建对象的时候会自动调用我';}public function __destruct(){echo '在销毁对象的时候会自动调用我';}}//测试__get$xiaoming=new Person();var_dump($xiaoming->name);//string(6)"小明"echo '<br />';var_dump($xiaoming->age);//int(18)var_dump($xiaoming->height);//NULL//测试__set$niu=new Person();$niu->name='小牛';echo '<br />';echo $niu->name; //小牛$niu->age=20;//age是受保护的变量,不能直接设置,设置时会调用__setecho $niu->age;//20//测试__unset$ma=new Person();/*unset($ma->name);echo $ma->name;//unexpected '$ma'*///销毁私有或受保护的属性echo '<br />';/*unset($ma->age);echo $ma->age;//Undefined property: Person::$age这样就销毁成功了*///测试__isset$hong=new Person();var_dump(isset($niu->age));//bool(false)echo '<br />';$hong->age=25;var_dump(isset($niu->age));//还是false//所以不能轻易判断出私有属性和受保护的属性是否存在//设置完__isset之后就变成true了//测试__construct$jun=new Person(); //输出:在创建对象的时候会自动调用我//测试__destructecho '<br />';unset($jun);
__toString
触发时机: echo一个对象的时候触发 (把对象当成字符串使用的时候自动执行)
该函数需要return一个字符串
<?phpclass Person{public $name;//要打印对象要写一个魔术方法public function __toString()//这个函数没有参数{return '我爱你中国';}}$niu = new Person();echo $niu;//不能通过echo来打印一个对象,要打印对象要写一个魔术方法//会打印出你return的字符串,这个字符串你可以打印这个对象自己的信息(拼接成一个字符串进行打印)
__invoke
触发时机:将对象当成函数的时候自动调用
__debugInfo
触发时机: var_dump一个对象的时候触发
该函数需要return一个数组
<?phpclass Person{public $name;public $age;public $height;//当通过var_dump打印对象的时候,我只想显示$age和$heightpublic function __debugInfo(){return ['age'=>$this->age,'height'=>$this->height];}}$niu = new Person();var_dump($niu);
__call
触发时机:当调用一个不存在对象方法的时候触发
参数1:函数名
参数2:是一个数组,函数中的参数都被存放到这个数组中
<?phpclass Person{public $name;public $age;public $height;//当你调用一个不存在的对象方法的时候就会自动调用__callpublic function test(){echo '这是test方法';}public function __call($name,$value){var_dump($name,$value);}}$niu = new Person();var_dump($niu);$niu->demo(1,2,3);//调用一个不存在的对象

__callStatic
触发时机:当调用一个不存在静态方法的时候触发
参数1:函数名
参数2:是一个数组,函数中的参数都被存放到这个数组中
[注]该方法也是static方法
call是调用对象方法
callStatic是调用静态方法
序列化和反序列化
我们在学习sleep和wakeup之前我们要先了解序列化和反序列化
参考:简单了解反序列化 (好好好)
Y4师傅的反序列化文章(大大的好)
serialize:序列化
unserialize:反序列化
序列化后的内容只有成员变量,没有成员函数
<?phpclass Person{public $name;public $age;public $height;public function __construct($name,$age,$height){$this->name=$name;$this->age=$age;$this->height=$height;}}$niu=new Person('niu',19,180);//如果我想保存$niu这个对象怎么保存?我们知道程序运行结束之后$niu占用的内存空间已经被释放掉了,//$niu这个对象只有在程序运行的时候才存在,脚本一结束,这些信息就都没有了//我们可以通过写入文件的形式将它的名字、年龄、身高都写入到文件中,就保存到磁盘中了,永久存在//当你想要保存一个对象的时候,你就可以将它序列化$str=serialize($niu);//会返回一个字符串echo $str; //O:6:"Person":3:{s:4:"name";s:3:"niu";s:3:"age";i:19;s:6:"height";i:180;}//生成字符串之后就可以写入文件中了file_put_contents('niu.txt', $str);//这样就达到完美保存一个对象的目的,不管程序有没有运行结束,这个对象都已经保存在本地
__sleep
触发时机:在序列化一个对象的时候调用
返回值:必须是一个数组,数组中写你想要序列的成员属性名
<?phpclass Person{public $name;public $age;public $height;public function __construct($name,$age,$height){$this->name=$name;$this->age=$age;$this->height=$height;}public function __sleep(){//echo '我要睡觉了';//现在只想序列化年龄和身高,所以就只需要返回属性即可return ['age','height'];//age和height都是一个属性名字符串}}$niu=new Person('niu',19,180);//如果我想保存$niu这个对象怎么保存?我们知道程序运行结束之后$niu占用的内存空间已经被释放掉了,//$niu这个对象只有在程序运行的时候才存在,脚本一结束,这些信息就都没有了//我们可以通过写入文件的形式将它的名字、年龄、身高都写入到文件中,就保存到磁盘中了,永久存在//当你想要保存一个对象的时候,你就可以将它序列化$str=serialize($niu);//会返回一个字符串echo $str; //O:6:"Person":3:{s:4:"name";s:3:"niu";s:3:"age";i:19;s:6:"height";i:180;}//生成字符串之后就可以写入文件中了file_put_contents('niu.txt', $str);//这样就达到完美保存一个对象的目的,不管程序有没有运行结束,这个对象都已经保存在本地//现在通过序列化将我们对象的年龄、名字、身高都保存到文件中,现在又一个需求,我只想让你保存年龄和身高怎么办?要用__sleep//O:6:"Person":2:{s:3:"age";i:19;s:6:"height";i:180;}
__wakeup
触发时机:在反序列化一个对象的时候调用
反序列成功之后,想要让对象执行一些初始化方法,可以写到这个函数中
<?phpclass Person{public $name;public $age;public $height;public function __construct($name,$age,$height){$this->name=$name;$this->age=$age;$this->height=$height;}public function __sleep(){//echo '我要睡觉了';//现在只想序列化年龄和身高,所以就只需要返回属性即可return ['age','height'];//age和height都是一个属性名字符串}public function __wakeup(){echo '我睡醒了';}}$niu=new Person('niu',19,180);//你保存到本地一个对象字符串之后,现在我想让你把这个对象再恢复,怎么恢复?//首先将这个字符串先读进来$str=file_get_contents('niu.txt');//反序列化$obj=unserialize($str); //通过你序列化的一个字符串,我可以反序列化成一个对象,在你反序列化的时候他会先执行__wakeup,在这里面你可以将自己的一些属性再设置一下var_dump($obj);/*输出:我睡醒了object(Person)#2 (3) {["name"]=>NULL["age"]=>int(19)["height"]=>int(180)}*/
__clone
触发时机:在克隆一个对象的时候调用
在这里面可以对克隆出来的对象的属性做一些操作
<?phpclass Person{public $name;public $age;public $height;public function __wakeup(){echo '我睡醒了';}public function __clone(){//这里面你可以对克隆出来的对象的属性做一些操作,比如我不想让他的年龄跟我一样$this->age=20;//可以对属性做一个简单的初始化}}$niu=new Person('niu',19,180);$obj=clone $niu;//将$niu这个对象克隆一份(就是制造一个一模一样的对象)var_dump($obj);//当你在克隆的时候会自动调用__clone
__autoload(这是唯一一个写在类外的魔术方法)
触发时机: new一个对象的时候,当前脚本没有这个类,那么会触发这个方法
参数: 就是该类的类名字符串
Dog.php
<?phpclass Dog{function wang(){echo '汪汪';}}
moshu.php
<?phpclass Person{public $name;public $age;public $height;public function __autoload($className)//自动加载{$file=$className.'php'; //通过类名找到文件名include $file;}}$dog=new Dog();//没有Dog这个类,当你去创建一个不存在的类的对象的时候,就会自动调用__autoload这个方法,这个方法是唯一写在类外的方法$dog->wang();//汪汪//工作中一个类就是一个完整的文件,文件名要和类名相同
