PHP 魔术方法
__sleep
,__wakeup
__sleep
在使用 serialize 方法进行序列化之前调用,返回需要进行序列化保存的属性数组,如果属性不在该数组里,存储的是属性的默认值,一般执行一些释放清理比较大变量的工作。__wakeup
在使用 unserialize 方法进行反序列化后调用,一般是生成对象后执行初始化工作。
Test.php
<?php
class Test
{
public $a = 'A';
protected $b = 'I am B';
private $c = 'B';
public function __construct()
{
$this->a='I am A';
$this->b=520;
$this->c="I am C";
}
public function test()
{
echo "\ntest method\n";
echo $this->a;
echo $this->b;
echo $this->c;
}
public function __sleep()
{
return ['a','c'];
}
public function __wakeup()
{
$this->test();
}
}
$test = new Test();
echo "\nserialize\n";
$s = serialize($test);
var_export($s);
echo "\nunserialze\n";
$o = unserialize($s);
var_export($o);
执行结果
serialize
'O:4:"Test":2:{s:1:"a";s:6:"I am A";s:7:"' . "\0" . 'Test' . "\0" . 'c";s:6:"I am C";}'
unserialze
test method
I am AI am BI am CTest::__set_state(array(
'a' => 'I am A',
'b' => 'I am B',
'c' => 'I am C',
))
__serialize
,__unserialize
这两个魔术方法 php7.4才支持,功能类似__sleep
和__wakeup
,不过__serialize
返回的是属性的 key => value 数组,__unserialize
需要手动解析数据__toString
把对象当字符串打印时会执行该方法,并且需要返回一个字符串
<?php
class Test
{
public $a = 'I am a string';
public function __toString()
{
return $this->a;
}
}
$o = new Test();
echo $o;
输出结果:I am a string
__invoke
当将对象当方法来调用时会触发该方法
<?php
class Test
{
public function __invoke($a, $b)
{
echo "Hello, I am from invoke\n";
echo "\n{$a}\n";
var_export(func_get_args());
}
}
$o = new Test();
$o("A","B", "C");
结果
Hello, I am from invoke
A
array (
0 => 'A',
1 => 'B',
2 => 'C',
)
__set_state
var_export 打印对象时会调用
<?php
class Test
{
public $a;
protected $b;
private $c;
public function __construct()
{
$this->a = 'AAA';
$this->b = 'BBB';
$this->c = 'CCC';
}
public function __set_state($data)
{
$o = new stdClass();
$o->d = $data['a'];
$o->e = $data['b'];
$o->c = $data['c'];
return $o;
}
}
$o = new Test();
$result = var_export($o, true);
eval('$tmp = ' . $result . ";");
var_export($tmp);
结果
stdClass::__set_state(array(
'd' => 'AAA',
'e' => 'BBB',
'c' => 'CCC',
))
__construct
实例化对象时执行构建函数__destruct
当对象引用被删除时,执行析构函数__set
,__get
,__isset
,__unset
__set
当对象设置一个不可访问属性或者不存在的属性名时,会触发该函数__get
当对象获取一个不可访问属性或不存在属性值时,会触发该函数__isset
判断对象属性是否存在,当属性是不可访问或不存在时会触发__unset
释放对象属性,当属性不可访问或不存在时会触发
<?php
class Test
{
public $a = 'AAA';
private $b = 'BBBB';
public function __set($key, $value)
{
echo "set {$key}={$value}\n";
$this->$key = $value;
}
public function __get($key)
{
echo "get {$key}=" . $this->$key;
}
public function __isset($name)
{
echo "trigger isset {$name}\n";
}
public function __unset($name)
{
echo "trigger unset {$name}\n";
}
}
$o = new Test();
$o->a="I am A\n";
$o->b="I am B\n";
$o->c="I am C\n";
echo $o->a . "\n";
echo $o->b . "\n";
echo $o->c . "\n";
echo $o->d . "\n";
var_export(isset($o->a));
echo "\n";
var_export(isset($o->b));
echo "\n";
var_export(isset($o->c));
echo "\n";
var_export(isset($a->d));
echo "\n";
unset($o->a);
unset($o->b);
unset($o->c);
unset($o->d);
结果
set b=I am B
set c=I am C
I am A
get b=I am B
I am C
PHP Notice: Undefined property: Test::$d in /Users/songzw/Downloads/require-include/call-static/set-get-test.php on line 16
get d=
true
trigger isset b
false
true
false
trigger unset b
trigger unset d
__call
,__callStatic
__call
当对象调用一个不存在的方法时会触发该函数__callStatic
当类调用一个不存在的类方法时会触发该函数
<?php
class Test
{
public function __call($method, $args)
{
echo "call method={$method},args=" . implode(',',$args) . "\n";
}
public static function __callStatic($method, $args)
{
echo "callStatic method={$method},args=" . implode(',',$args) . "\n";
}
}
$o = new Test();
$o->test1('aaa','bbb');
Test::testStatic1('ccccc','dddddd');
结果
call method=test1,args=aaa,bbb
callStatic method=testStatic1,args=ccccc,dddddd
__clone
当使用 clone 来复制对象时,会触发该函数,可用于禁止拷贝对象或拷贝时修改属性
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: