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 协议》,转载必须注明作者和本文链接
雪花飘
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!