首頁 > 軟體

php反序列化之魔術方法超詳細講解

2022-11-03 14:01:02

php魔術方法

在php類保留方法中以 “__”兩個下劃線開頭的函數稱為魔術方法,我的理解為php類設計中自定義好的函數。

常見的魔術方法有:

__construct(),類別建構函式
__destruct(),類的解構函式
__call(),在物件中呼叫一個不可存取方法時呼叫
__callStatic(),用靜態方式中呼叫一個不可存取方法時呼叫
__get(),獲得一個類的成員變數時呼叫
__set(),設定一個類的成員變數時呼叫
__isset(),當對不可存取屬性呼叫isset()或empty()時呼叫
__unset(),當對不可存取屬性呼叫unset()時被呼叫
__sleep(),執行serialize()時,先會呼叫這個函數
__wakeup(),執行unserialize()時,先會呼叫這個函數
__toString(),類被當成字串時的迴應方法
__invoke(),呼叫函數的方式呼叫一個物件時的迴應方法
__set_state(),呼叫var_export()匯出類時,此靜態方法會被呼叫
__clone(),當物件複製完成時呼叫
__autoload(),嘗試載入未定義的類
__debugInfo(),列印所需偵錯資訊

__construct()與__destruct()

__construct() 建構函式與 __destruct() 解構函式,與其他的語言如java,c#,一樣,建構函式就是在物件範例化的時候先執行初始化的方法。

__construct()建構函式只有在new 一個物件的時候會觸發,在serialize 序列化和unserialize反序列化中都不會觸發

<?php
class demo1{
    private $k1;
    public function __construct()
    {
        echo("建構函式被呼叫"."<br>");
    }
    public  function f1(){
        echo("f1 函數被呼叫");
    }
}
echo("0000"."<br>");
$f=new demo1();
echo("1111"."<br>");
$a=serialize($f);
echo("2222"."<br>");
unserialize($a);
?>

輸出結果

__destruct() 解構函式則在物件銷燬和serialize 反序列化的情況下會被觸發。如下

<?php
class demo1{
    private $k1;
    public function __destruct()
    {
        echo("解構函式被呼叫"."<br>");
    }
}
$f=new demo1();
echo("0000"."<br>");
$a=serialize($f);
echo("1111"."<br>");
unset($f);
echo("2222"."<br>");
unserialize($a);
?>

輸出結果

__call

__call 魔術方法的作用是當前物件呼叫一個不存在的方法時,就會被觸發

<?php
class demo1{
    private $k1;
    public  function f1(){
        echo("f1 函數被呼叫");
    }
	  //當呼叫不存在的方法時,方法名作為引數傳到$name 變數,方法名的輸入引數傳到arguments參數列中
    public function __call($name, $arguments)
    {
        // TODO: Implement __call() method.
        echo($name."---".$arguments[0]);
    }
}
$f=new demo1();
$f->f2("123");//呼叫不存在的方法f2()
?>

輸出結果

__get

__get() 魔術方法是當存取一個物件不存在的變數時就會被觸發

<?php
class demo1{
    private $k1;
    public  function f1(){
        echo("f1 函數被呼叫");
    }
    public function __get($name)//不存在的變數k會以引數傳到$name
    {
        echo($name);
    }
}
$f=new demo1();
$f->k;//不存在的變數k
?>

輸出結果

__set

__set() 魔術方法是當給一個物件不存在的變數賦值時就會被觸發

<?php
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
class demo1{
    private $k1;
    public  function f1(){
        echo("f1 函數被呼叫");
    }
    public function __set($name, $value)
    {
        echo($name."---".$value);
    }
}
$f=new demo1();
$f->k=123; //給不存在的成員變數賦值
?>

輸出結果

__isset

當對不可存取屬性呼叫isset()或empty()時會觸發,例如存取類的私有屬性,類不存在的成員屬性

<?php
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
class demo1{
    private $k1;
    public  function f1(){
        echo("f1 函數被呼叫");
    }
    public function __isset($name)
    {
       echo($name);
    }
}
$f=new demo1();
$f2=unserialize(serialize($f));//反序列化
isset($f2->k1);//使用isset方法判斷私有成員屬性k1
empty($f2->k1);//使用empty方法判斷私有成員屬性k1
?>

輸出結果

__unset

當嘗試使用unset() 銷燬函數去銷燬一個不可存取的成員屬性時會觸發,不可存取(包括私有成員屬性,不存在的成員屬性)

<?php
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
class demo1{
    private $k1;
    public  function f1(){
        echo("f1 函數被呼叫");
    }
    public function __unset($name)
    {
        echo($name);
    }
}
$f=new demo1();
$f2=unserialize(serialize($f));//反序列化
unset($f2->k1);//使用unset銷燬私有成員屬性k1
unset($f2->faaa);//使用unset銷燬不存在的成員屬性faaa
?>

輸出結果

__sleep

當物件被serialize 序列化時觸發呼叫__sleep

<?php
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
class demo1{
    private $k1;
    public  function f1(){
        echo("f1 函數被呼叫");
    }
    public function __sleep()
    {
        echo("在被序列化時被呼叫");
    }
}
$f=new demo1();
echo("00000"."</br>");
serialize($f);
?>

輸出結果

__wakeup

當進行unserialize 反序列化物件時,__wakeup魔術方法會被觸發,看起來__wakeup與__sleep 觸發條件是相反的

<?php
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
class demo1{
    private $k1;
    public  function f1(){
        echo("f1 函數被呼叫");
    }
    public function __wakeup()
    {
        echo("在被反序列化時被呼叫");
    }
}
$f=new demo1();
$uz=serialize($f);
echo("00000"."</br>");
unserialize($uz);
?>

輸出結果

__toString

如果一個物件類中存在__toString魔術方法,這個物件類被當做字串進行處理時,就會觸發__toString魔術方法,而不會產生錯誤

<?php
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
class demo1{
    private $k1;
    public  function f1(){
        echo("f1 函數被呼叫");
    }
    public function __toString()
    {
        echo("__toString 被觸發了");
        return "";
    }
}
$f=new demo1();
echo($f);
?>

輸出結果

__invoke

當一個物件類中存在__invoke魔術方法,這個物件類被當作函數進行呼叫時,就會觸發__invoke魔術方法,而不會產生錯誤

<?php
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
class demo1{
    private $k1;
    public  function f1(){
        echo("f1 函數被呼叫");
    }
    public function __invoke()
    {
       echo("__invoke 被觸發了");
    }
}
$f=new demo1();
$f();
?>

輸出結果

到此這篇關於php反序列化之魔術方法超詳細講解的文章就介紹到這了,更多相關php反序列化 內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com