2024.3.20
1、
__construct()
__construct() 用于在创建对象时自动触发
当使用 new 关键字实例化一个类时,会自动调用该类的 __construct() 方法
<?php
class MyClass {
public function __construct() {
echo "已触发 __construct 一次";
}
}
$obj = new MyClass(); // 创建对象时会输出 "已触发 __construct 一次"
?>
2、__destruct()
__destruct() 用于在对象被销毁时自动触发
对象的销毁对象的引用计数减少为零来触发
<?php
class MyClass {
public function __construct() {
echo "已触发 __construct 一次\n";
}
public function __destruct() {
echo "已触发 __destruct 一次\n";
}
}
$obj = new MyClass(); //会触发 __construct
$a = unserialize($obj) //会触发 __destruct
?>
//由于php存在自动回收机制,在代码结束后会销毁 $obj 从而再一次触发 __destruct
//所以这段代码最终互返回两次"已触发 __destruct 一次"
3、__sleep()
序列化serialize() 函数会检查类中是否存在一个魔术方法sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。
此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组
如果该方法未返回任何内容,则 NULL 被序列化,并产生一个 E_NOTICE 级别的错误
<?php
class test
{
public $var_1;
public $var_2;
public function __sleep() //在对象被序列化时触发
{
echo "已触发 __sleep() 一次\n";
return ['var_1','var_2'];
}
}
$a = new test();
$a -> var_1 = 'var1';
$a -> var_2 = 'var2';
$b = serialize($a); //会触发 __sleep
var_dump($b);
?>
4、__weekup()
__weekup() 用于在反序列化对象时自动调用
unserialize() 会检查是否存在一个 wakeup() 方法,
如果存在,则会先调用wakeup()方法,预先准备对象需要的资源,返回void
常用于反序列化操作中重新建立数据库连接或执行其他初始化操作
<?php
class test
{
public $var_1;
public $var_2;
public $var_wakeup;
public function __wakeup() //在对象被反序列化时触发
{
echo "已触发 __wakeup 一次\n";
$this -> var_wakeup = $this -> var_1;
}
}
$a = new test();
$a -> var_1 = 'var1';
$a -> var_2 = 'var2';
$b = serialize($a);
$c = unserialize($b); //会触发 __wakeup
var_dump($c);
?>
5、__tostring()
__tostring() 在对象被当做字符串处理时自动调用
比如echo、==、preg_match()
<?php
class test
{
public $var_1;
public function __tostring() //对象被当做字符串处理时触发
{
echo "已触发 __tostring 一次\n";
return '1';
}
}
$a = new test;
$a == '123'; //会触发 __wakeup
echo $a; //会触发 __wakeup
?>
6、__invoke()
__invoke() 在对象被当做函数处理时自动调用
<?php
class test
{
public $var_1='1';
public function __invoke() //对象被当做函数处理时触发
{
echo "已触发 __invock 一次\n";
}
}
$a = new test('1');
$a(); //以函数的形式处理 $a 从而触发__invoke
?>
7、__call()
__call() 在调用一个不存在的方法时触发
<?php
class test
{
public function __call($method, $args) //当调用一个不存在的方法时触发
{
echo "已触发 __call 一次\n";
}
}
$a = new test;
$a -> nothingness(''); //因为nothingness()方法不存在,所以触发了 __call
?>
8、__callStatic()
__callStatic() 在静态调用或调用成员常量时使用的方法不存在时触发
<?php
class test
{
static public function __callStatic($method, $args)
{
echo "已触发 __callStatic 一次\n";
}
}
$a = new test(1);
$a::nothingness('a');
?>
9、__set()
__set() 在给不存在的成员属性赋值时触发
<?php
class test
{
public $var_1;
public $temp;
public function __construct($var) //在对象被创建时触发
{
echo "已触发 __construct 一次\n";
$this -> var_1 = $var;
$this -> var_nothingness = '114514';
}
public function __set($name, $value) //在给不存在的成员属性赋值时触发
{
echo "已触发 __set 一次\n";
}
}
$a = new test(1);
?>
10、__isset()
__isset() 在对不可访问属性使用 isset() 或empty() 时会被触发
<?php
class temp
{
private $no;
public function __isset($name) //在给不存在的成员属性赋值时触发
{
echo "已触发 __isset 一次\n";
}
}
class test
{
public $var;
public $temp;
public function __construct($var)
{
echo "已触发 __construct 一次\n";
$this -> var_1 = $var;
$temp = new temp;
empty($temp->no); //用于触发 __isset
}
}
$a = new test(1);
?>
11、__unset()
__unset() 在对不可访问属性使用 unset() 时会被触发
<?php
class temp
{
private $no;
public function __unset($name) //对不可访问属性使用 unset() 会被触发
{
echo "已触发 __unset 一次\n";
}
}
class test
{
public $var;
public $temp;
public function __construct($var)
{
echo "已触发 __construct 一次\n";
$this -> var_1 = $var;
$temp = new temp;
unset($temp->no);
}
}
$a = new test(1);
?>
12、__clone()
__clone() 当使用 clone 关键字拷贝完成一个对象后就会触发
<?php
class test
{
public $var;
public function __construct($var)
{
echo "已触发 __construct 一次\n";
$this -> var_1 = $var;
clone($this); //用于触发 __clone
}
public function __clone() //当使用 clone 关键字拷贝完成一个对象后就会触发
{
echo "已触发 __clone 一次\n";
}
}
$a = new test(1);
?>
13、__get()
__get() 当尝试访问不可访问属性时会被自动调用
<?php
class Test
{
private $data = array();
public function __construct($var)
{
echo "已触发 __construct 一次\n";
$this->var_1 = $var;
}
public function __get($name)
{
echo "已触发 __get 一次\n";
if (isset($this->data[$name])) {
return $this->data[$name];
}
}
public function __set($name, $value)
{
echo "已触发 __set 一次\n";
$this->data[$name] = $value;
}
}
$a = new Test(1);
$a->v = 'a'; // 设置属性
echo $a->v; // 访问属性
var_dump($a);
?>
警告:以下代码是个人研究时写的,异常混乱,没有任何的逻辑和结果可言,大佬勿看,看完容易高血压,萌新勿看,看完容易裂开
<?php
class temp
{
private $no;
public function __isset($name) //对不可访问属性使用 isset() 或empty() 会被触发
{
echo "已触发 __isset 一次\n";
}
public function __unset($name) //对不可访问属性使用 unset() 会被触发
{
echo "已触发 __unset 一次\n";
}
}
class test
{
public $var_1;
public $var_2;
public $var_wakeup;
public $temp;
private $data = array();
public function __construct($var) //在对象被创建时触发
{
echo "已触发 __construct 一次\n";
$this -> var_1 = $var;
}
public function __destruct() //在对象被销毁时触发
{
echo "已触发 __destruct 一次\n";
$this(); //用于触发 __invoke
}
public function __sleep() //在对象被序列化时触发
{
echo "已触发 __sleep() 一次\n";
$this::nothingness(''); //用于触发 __call
$this -> var_nothingness = '114514'; //用于触发 __set
return ['var_1','var_2'];
}
public function __wakeup() //在对象被反序列化时触发
{
echo "已触发 __wakeup 一次\n";
if($this -> var_2 == '') //用于触发 __tostring
{
echo "比较通过\n";
}
$this -> var_wakeup = $this -> var_1;
}
public function __tostring() //对象被当做字符串处理时触发
{
echo "已触发 __tostring 一次\n";
return '1';
}
public function __invoke() //对象被当做函数处理时触发
{
echo "已触发 __invock 一次\n";
}
public function __call($method, $args) //当调用一个不存在的方法时触发
{
echo "已触发 __call 一次\n";
clone($this); //用于触发 __clone
}
static public function __callStatic($method, $args) //在静态调用或调用成员常量时使用的方法不存在时触发
{
echo "已触发 __callStatic 一次\n";
$temp = new temp;
isset($temp -> no); //用于触发 __isset
unset($temp -> no); //用于触发 __unset
}
public function __clone() //当使用 clone 关键字拷贝完成一个对象后就会触发
{
echo "已触发 __clone 一次\n";
}
public function __get($name) //当尝试访问不可访问属性时会被自动调用
{
echo "已触发 __get 一次\n";
$this-> name = "$name"; //用于触发 __set
}
public function __set($name, $value) //在给不存在的成员属性赋值时触发
{
echo "已触发 __set 一次\n";
$this->data[$name] = $value;
}
}
//会触发一次 __construct 并在对象被销毁时触发一次 __destruct
//然后 __destruct 中的 $this() 又会触发 __invoke
$a = new test('var1');
//会触发一次 __construct 并在对象被销毁时触发一次 __destruct
//然后 __destruct 中的 $this() 又会触发一次 __invoke
$a -> var_2 = new test('var2');
//因为 $a 是一个对象,$a -> var_2 又是一个对象,会触发两次 __sleep
//__sleep中会调用不存在的函数和给不存在的值赋值,又会触发 __call 和 __set
//__call又会触发一次 __clone 和一次 __destruct
$b = serialize($a);
//同理会触发会先触发两次 __wakeup 再触发两次 __destruct
//然后 __destruct 中的 $this() 又会触发 __invoke
//__wakeup中有比较,所以又会触发一次 __tostring
//注意:__tostring 是由 $a -> var_2 触发的,而 $a -> var_2 -> var_2 由于值为 NULL 是不会触发__tostring的
$c = unserialize($b);
//会触发一次 __callStatic
//__callStatic 里面的 isset 会触发一次 __isset,unset 会触发一次 __unset
$c::nothingness('');
//会触发一次 __get
//__get 又触发一次 __set
echo $c -> v;
//var_dump($c);