PHP 魔術方法

雪花飄發表於2021-04-18
  • __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 協議》,轉載必須註明作者和本文連結
雪花飄

相關文章