16個(gè)PHP開發者必知必會的魔術(sh少紅ù)方法​!

分類:└ 技術(shù)前沿,來源:江門深圳市鄉個巨鳥網絡科技有限公司有限公司


方法名描述
__construct()類的構造函數
__destruct()類的析構函數
__call($funName, $arguments)當調用一個(gè)未定義或不可(kě)達方法時, __call() 方法答費将被調用。
__callStatic($funName, $arguments)當調用一個(gè)未定義或不可(kě)達的靜态方法討視時, __callStatic() 方法将被調用知得。
__get($propertyName)當獲取一個(gè)類的成員變量時, __get() 方法将老著被調用。
__set($property, $valu湖畫e)當賦值一個(gè)類的成員變量時, __set() 方法将被調離站用。
__isset($content)當調用 isset() 或 empty() 對一個(gè)未定義或不可(媽窗kě)達的成員賦值時, __isset() 方法将被調用裡微。
__unset($content)當調用 reset() 對一個(gè)未定義或不可(kě)信問達的成員更新時, __unset() 方法将被調用。
__sleep()當執行序列化 serialize() 時,__sleep() 方法将首電中先被調用。
__wakeup()當執行反序列化 deserialization()黃醫 時, __wakeup() 方法将首先被調用。
__toString()當使用 echo 方法直接輸出顯示對象時,__toString() 方法舞能首先被調用。
__invoke()使用調用函數(function)訪問(wèn)一個(gè)對象時, __西數invoke() 方法将首先被調用。
__set_state($an_array)當調用 var_export() 方法時,__農還set_state() 方法将被調用。
__clone()當對象被複制賦值時,__clone() 方法将被調用。
__autoload($className)試圖載入一個(gè)未定義的類時調用。
__debugInfo()輸出 debug 信息。



範例

下(xià)面讓我們以實例的形式向大家講解下(xià)這幾個(gè)魔術筆有(shù)方法時如(rú)何使用的。


一、 __construct(),類的構造函數

php中(zhōng)構造方法是對象創建完成後第一個(gè)被對有花象自動(dòng)調用的方法。在每個(gè)類中(zhōng)都有一個廠姐(gè)構造方法,如(rú)果沒有顯示地聲明它,那麼類要影中(zhōng)都會默認存在一個(gè)沒有參又從數且内容為空的構造方法。


1、 構造方法的作用


通(tōng)常構造方法被用來執行一些有用的初始化都秒任務,如(rú)對成員屬性在創建對象時賦予初始值。


2、 構造方法的在類中(zhōng)的聲明格式


function __constrct([參數列表]友可){


    方法體 //通(tōng)件空常用來對成員屬性進行初始化賦值

}

3、 在類中(zhōng)聲明構造方法需要注意的事項


1、在同一個(gè)類中(zhōng)隻外時能聲明一個(gè)構造方法,原因是,PHP不支持構造函北下數重載。


2、構造方法名稱是以兩個(gè)下(xià)畫線開始的__con場物struct()

下(xià)面是它的例子(zǐ):


<?php

    class Person見身

    {    &nbs男日p;         &n理鐵bsp;       外匠         子你       &nbs銀是p;      東學;      到和         &劇報nbsp;     &n西麗bsp;   

       校拿;     public $na筆做me;        

      &音費nbsp;     public $紅唱age;    &nb湖舞sp;   

         通兒;   public $sex;    &n如我bsp;   

      &n購靜bsp;     &nbs店請p;        術紅           &n不年bsp;      化拿;       &nb煙習sp;     &n紙國bsp;       &場近nbsp;    

       工那 /**

         妹但* 顯示聲明一個(gè)構造方法且帶參數

      用校   */   分文;         &nb土章sp;     &n中議bsp;      做男       &唱間nbsp;        如校         &nbs分房p;           &術內nbsp;        志商;           &n上照bsp;    

      &n藍討bsp; public function __construct($name=是筆"", $sex="男購機(nán)", $age=22)

        {  &n們亮bsp;   

      &nbs術做p;     $thi電拿s->name = $name;

       他什     $this->se你工x = $sex;

      &nb技自sp;     $this->age 長好= $age;

        }

        

        /**

       機雨;  * say 方法

         */

        但內public function say()

      時話  { 

          &nb門亮sp; echo "我叫:" . $this-&g費鐵t;name . ",性别:" . $this->藍地sex . ",年齡:" 為嗎. $this->age;

       外拍 }   

        &nb山腦sp;     &n和信bsp;       &n水什bsp;         &nbs能到p;         &n機計bsp;       &nbs跳遠p;      明吧;     &nbs快船p;       &nb票拿sp;         &nbs道吧p;     &nb就資sp;    

    }

創建對象$Person1且不帶任參數


$Person1 = new Person();師新

echo $Person1->say(); /煙錢/輸出:我叫:,性别:男(nán),年齡:27

創建對象$Person2且帶參數“小明”


$Person2 = new Person("小黃校明");

echo $Person2->say(); //輸出:我坐湖叫:張三,性别:男(nán),年齡:27

創建對象$Person3且帶三個(gè)參數唱兒


$Person3 = new Person("李四&歌林quot;,"男(nán)",25);

echo $Person3->say(); 技麗//輸出:我叫:李四,性别:男(nán),年齡:25

二、__destruct(),類的析構函數

通(tōng)過上面的講解,現在我們已經知道了什麼叫構造方法。那麼與構造短弟方法對應的就是析構方法。


析構方法允許在銷毀一個(gè)類之前執行的一些花算操作或完成一些功能,比如(rú)說關(guān)閉文(wén)件、釋放結果集大工等。


析構方法是PHP5才引進的新内容。


析造方法的聲明格式與構造方法 __construct() 比較相內類似,也是以兩個(gè)下(xià)劃線開始的方法 __destr我愛uct() ,這種析構方法名稱也是固定的。


1、 析構方法的聲明格式


function __destruct()

{

 //方法體

}

注意:析構函數不能帶有任何參數。


2、 析構方法的作用


一般來說,析構方法在PHP中(zhōng)并不件很是很常用,它屬類中(zhōng)可(kě)選擇的一部分,通(tōng)常用件老來完成一些在對象銷毀前的清理任務。

舉例演示,如(rú)下(xià):


<?php

class Person{     兒呢;

          &n火服bsp;       &師藍nbsp;      吧了;      廠這;         &nb討輛sp;     &nbs雜事p;         離相;

    public $name; 笑資;      海麗  

    public $age; 懂懂        

    public $sex;  人些       

       影腦           &報藍nbsp;       &nbs購兒p;           &體器nbsp;         &nbs呢為p;     &nb但議sp;       &知快nbsp;     

    public func讀黃tion __construct($name="城習", $sex="男(n跳自án)", $age=22)

    {   匠火;

       黃習; $this->name = $name;

      去校  $this->sex&n農醫bsp; = $sex;

      &n藍飛bsp; $this->age  = $age;

    }

    

    /**

     * say 說話方法

     電舊*/

    public function 街時say()

    {  

        echo "如章我叫:".$this->name.個子",性别:".$this->sex.&qu小但ot;,年齡:".$this->age爸些;

    }  上理  

    

    /**

     * 聲明一錢呢個(gè)析構方法

     */

    public function __dest街什ruct()

    {

         聽火;   echo "我覺得我還可(kě)以再搶救件雪一下(xià),我的名字叫".$照師this->name;

    }

}


$Person = new Person("小明&quo就花t;);

unset($Person); //銷毀上面創建的對象$Perso地好n

上面的程序運行時輸出:


我覺得我還可(kě)以再搶救一下(xià),我的名字叫小明

三、 __call(),在對象中(zhōng)調用一個(gè)不可(kě)和上訪問(wèn)方法時調用。

該方法有兩個(gè)參數,第一個(gè)參數 $funct空讀ion_name 會自動(dòng)接收不存在的方法名,議近第二個(gè) $arguments 則以間相數組的方式接收不存在方法的多個(gè)參數體頻。


1、 __call() 方法的格式:


function __call(string $fu明你nction_name, array $argumen紙校ts)

{

    // 方法體

}

2、 __call() 方法的作用:


為了避免當調用的方法不存在時産生錯誤,而意外的導緻程序中(zhōng)開區止,可(kě)以使用 __call() 方法來避免。


該方法在調用的方法不存在時會自動(dòn森廠g)調用,程序仍會繼續執行下(xià)去。

請參考如(rú)下(xià)代碼:


<?php

class Person

{      &n村問bsp;          制吧;        開懂;    

    function say(高從)

    { &nb那火sp;

       近美;          說視;     &nbs劇好p;      &火術nbsp;

          &nb土地sp;echo "Hello, worl綠一d!
"; 

    }     去拍 

        

    /**

     * 聲明此方法用來處理調用對象中木多(zhōng)不存在的方法

     */

    function __學物call($funName, $argu錯朋ments)

    { 

          ech日舞o "你(nǐ)所調用的函數:&quo吃秒t; . $funName . "(年門參數:" ;  //風計 輸出調用不存在的方法名

        &nb鐘媽sp; print_r($arguments);在路 // 輸出調用不存在的方法時的參數列表

          echo些議 ")不存在!
\n"; // 結束換行  &nbs歌站p;           會我        

    }      唱務      &n海路bsp;     &nbs們畫p;         &nb從他sp;       &nbs資員p;     

}

$Person = new Person()機分;          刀行  

$Person->run("teacher"土睡;); // 調用對象中(zhōng)不存在的方法,則自動(dòng)要頻調用了對象中(zhōng)的__call()方法光通

$Person->eat("不河;小明", "蘋果&qu少土ot;);         鐘亮    

$Person->say();    &紙的nbsp;        道樹       &n上關bsp;   

運行結果:


你(nǐ)所調用的函數:run(參數:Arr唱購ay ( [0] => teacher ) 年呢)不存在!


你(nǐ)所調用的函數:eat(參數:Array ( 生玩[0] => 小明 [1] => 蘋果 ) )煙鐘不存在!


Hello, world!

四、 __callStatic(),用靜态方式中(zh錢她ōng)調用一個(gè)不可(kě)訪問(wèn)方法時調用

此方法與上面所說的 __call() 功能除了 __callSta公通tic() 是未靜态方法準備的之外,其它都男道是一樣的。


請看下(xià)面代碼:


<?php

class Person

{

    functio內還n say()

    {


     不房   echo "Hello, world!
";

    }


    /**

     * 聲裡些明此方法用來處理調用對象中(zhōng)不存在的方法

     */

    public stat兒報ic function __callStatic($funName, $雜大arguments)

    {

        echo &quo道聽t;你(nǐ)所調用的靜态方法:" . $fu可店nName . "(參數:" ;  //吃農 輸出調用不存在的方法名

     森些   print_r($arguments); 知山// 輸出調用不存在的方法時的參數列表

       照船 echo ")不存在!
\n"; // 結束換行

    }

}

$Person = new Person愛書();

$Person::run("teacher&qu有筆ot;); // 調用對象中(zhōng)不存在的方法,則自動朋新(dòng)調用了對象中(zhōng)的_音技_call()方法

$Person::eat("小明"城北;, "蘋果");

$Person->say();

運行結果如(rú)下(xià):


你(nǐ)所調用的靜态方法:run(參數:Ar男件ray ( [0] => teacher ) )不存在!

你(nǐ)所調用的靜态方法:eat(參數:Array ( [0] =&了小gt; 小明 [1] => 蘋果 ) )不存在!

Hello, world!

五、 __get(),獲得一個(gè)類的成員變量時調門光用

在 php 面向對象編程中(zhōng),類的成員屬性被設定為 private如可 後,如(rú)果我們試圖在外面調用它則會出現“不能訪問(w些拍èn)某個(gè)私有屬性”的錯誤。那麼為了解決這個(我拍gè)問(wèn)題,我們可(kě)以使用魔術(shù)方法 __get()。作時


魔術(shù)方法__get()的作用


在程序運行過程中(zhōng),通(tōng)過它可(kě)以在對象些在的外部獲取私有成員屬性的值。

我們通(tōng)過下(xià)面的 __get() 的實例來更進一步的連接它票視吧:


<?php

class Person

{

    private $name;

    private $age;


    function __construct($na但外me="", $age=1)

    {

        $this水花->name = $name;

     會去   $this->age = $age;

    }


    /**

     * 湖嗎在類中(zhōng)添加__get()方法,在直接獲取屬性值時自動拍懂(dòng)調用一次,以屬性名作為參數傳入并處理

     看湖* @param $propertyName

     *人跳

     * @return int

     */

    public func爸市tion __get($propertyName)

    {   筆紅

        if ($prop視制ertyName == "age&qu子行ot;) {

         學校   if ($this->age > 30) {

     日北         &nbs雜北p; return $this->道姐age - 10;

        &nbs冷錯p;   } else {

          &議去nbsp;     return $請黃this->$propertyName;

      &愛金nbsp;     }

        姐都} else {

      &nb自為sp;     return $this->$p頻鐵ropertyName;

        }

    }

}

$Person = new Person("們亮小明", 60);   湖問;// 通(tōng)過Person類實例化的對象,并通(tōng)過音公構造方法為屬性賦初值

echo "姓名:"不土 . $Person->name . "
";   // 直接訪問(w志動èn)私有屬性name,自動(dòng)調用了__get水身()方法可(kě)以間接獲取

echo "年齡:" . $Pe謝知rson->age . "
";    // 自動(dòng)調用了__ge什話t()方法,根據對象本身的情況會返回不同的值

運行結果:


姓名:小明

年齡:50

六、 __set(),設置一個(gè)類的成員變量時調用

__set() 的作用:


__set( $property, $v新生alue )` 方法用來設置私有屬性, 給一個(gè)未定義的屬性賦值時土山,此方法會被觸發,傳遞的參數是被設置的屬性名和(hé)值。


請看下(xià)面的演示代碼:


<?php

class Person

{

    private $na和門me;

    private $age;頻志


    public function _線我_construct($name=&quo樹秒t;",  $age=25)

    {

        $this->長金;name = $name;

        $this-&g房醫t;age  = $age;

    }


    /**

     * @param $我醫property

     * @param $value

     */

    public 黃書function __set($property, $value科通) {

        if ($pro東從perty=="age")

        {

        &靜務nbsp;   if ($value > 150 || $報也value < 0) {

          &長很nbsp;     return;

          &nb街師sp; }

        }

        $this-&g微公t;$property = $value;

    }


    /**

     * 在類中(zhōng城農)聲明說話的方法,将所有的私有屬性說出

     */

    public function湖能 say(){

      &樂熱nbsp; echo "我叫".$河線this->name.",今年".$th外吧is->age."歲了"資問;

    }

}


$Person=new Person("小明", 25);我熱 //注意,初始值将被下(xià)面所改變

//自動(dòng)調用了__set()老也函數,将屬性名name傳給第一個(gè)參男紅數,将屬性值”李四”傳給第二個(gè)參數體森

$Person->name = "小紅";&劇民nbsp;    //賦藍錯值成功。如(rú)果沒有__set(),則出錯。

//自動(dòng)調用了__set()函數,将屬性我暗名age傳給第一個(gè)參數,将屬性值26如要傳給第二個(gè)參數

$Person->age = 16; //賦值成功

$Person->age = 160; /做那/160是一個(gè)非法值,賦值失效

$Person->say();  //輸出:我叫小資線紅,今年16歲了

運行結果:


我叫小紅,今年16歲了

七、 __isset(),當對不可(kě)訪問(wèn)現草屬性調用isset()或empty()時調用

在看這個(gè)方法之前我們看一下(xià)isset()函數的應用,iss金件et()是測定變量是否設定用的函數,傳入一個(gè)變量作為參數,如(rú)為腦果傳入的變量存在則傳回true,否則傳回false。


那麼如(rú)果在一個(gè)對象外面使用isset()這個(gè)函從姐數去測定對象裡面的成員是否被設定可(kě)不可(kě)以北用用它呢(ne)?


分兩種情況,如(rú)果對象裡面成員是公有的,我們鐵草就可(kě)以使用這個(gè)函數來測定成員屬性,如(rú)果是私有的成員來事屬性,這個(gè)函數就不起作用了,原因就是因為私有的被封裝了,在外部不可南物(kě)見。那麼我們就不可(kě)以在對象的外部使用isset()函數來近什測定私有成員屬性是否被設定了呢(ne)?當然是可(kě)以的,市女但不是一成不變。你(nǐ)隻要在類裡面加上一個(gè)__isset雪黃()方法就可(kě)以了,當在類外部使用isset()服司函數來測定對象裡面的私有成員是否被設定時,就會自動(年男dòng)調用類裡面的__isset()方法了幫我們完成這樣的操作。


__isset()的作用:當對不可(kě)訪問(wèn)屬性請農調用 isset() 或 empty() 短歌時,__isset() 會被調用。


請看下(xià)面代碼演示:


<?php

class Person

{

    public $sex;

    private $name;

    private $age;


    public function __件頻construct($name=""飛外,  $age=25, $sex='男(nán)'大做;)

    {

        $黑科this->name = $name;

        答房$this->age  = $age;

        $this->s遠窗ex  = $sex;

    }


    /**

     *兵農 @param $content

     *

     * @return boo是看l

     */

    public f的窗unction __isset($content) {

      &nb做來sp; echo "當在類外部使用isset(煙大)函數測定私有成員{$content}時,自動(dòn這照g)調用
";

      &場船nbsp; echo  isset($this-&妹間gt;$content);

    }

}


$person = new Person("小明"他請, 25); // 初始賦值

echo isset($person->sex),"看房;
";

echo isset($person->name),"
";

echo isset($person->age),&q吧信uot;
";

運行結果如(rú)下(xià):


1 // public 可(kě)以 isset()

當在類外部使用isset()函數測定私有成員na拿中me時,自動(dòng)調用 // __但東isset() 内 第一個(gè)ech我很o

1 // __isset() 内第二個(g輛雜è)echo

當在類外部使用isset()函數測定私有成員age時,自動(dòng)調到道用 // __isset() 内 第一個(gè)echo

1 // __isset() 内第二個(gè)echo

八、 __unset(),當對不可(kě)訪問(wèn)屬性調用uns關慢et()時被調用。

看這個(gè)方法之前呢(ne),我們也先來看一下(xià日小) unset() 函數,unset()這個(gè)函數們用的作用是删除指定的變量且傳回true,參數為要删除的變量。


那麼如(rú)果在一個(gè)對象外部去删除對象内部的成員屬性用u綠制nset()函數可(kě)以嗎?


這裡自然也是分兩種情況:


1、 如(rú)果一個(gè)對象裡面的成員屬性是公有的,就暗海可(kě)以使用這個(gè)函數在對象外面删除對象的公有理關屬性。


2、 如(rú)果對象的成員屬性是私有的,我使用這個(gè)函數就沒有權限如哥去删除。


雖然有以上兩種情況,但我想說的是同樣如(rú)果你(nǐ)在一個(gè司火)對象裡面加上__unset()這個(gè鐵術)方法,就可(kě)以在對象的外部去删除對象的私有成員屬會黑性了。在對象裡面加上了__unset()這個(gè)方法之後,在對象熱綠外部使用“unset()”函數删除對象内部的私有成員屬性時,對話頻象會自動(dòng)調用__unset()函數來幫我們删除對議廠象内部的私有成員屬性。


請看如(rú)下(xià)代碼:


<?php

class Person

{

    public $sex;但一

    private $name;

    privat子事e $age;


    public function __c黃說onstruct($name="",又房  $age=25, $sex南樹='男(nán)')

    {

        說銀$this->name = $name;

      &n黃議bsp; $this->age 聽吃 = $age;

      &nbs麗弟p; $this->sex  = $sex少些;

    }


    /**

     * @param $con什長tent

     *

     * @re聽術turn bool

     */能如

    public functio新能n __unset($content) {

      &n女報bsp; echo "當在類外部使用unset()函數來删除私低公有成員時自動(dòng)調用的
";

     頻海   echo  isset($this看票->$content);

    }

}


$person = new Person("小明&quo見長t;, 25); // 初始賦值

unset($person->sex);

unset($person->name);

unset($person->age);

運行結果:


當在類外部使用unset()函數來删除私有成員時自動(dòng)調用的路新

1當在類外部使用unset()函數來删除私有成員時自動(d為懂òng)調用的

1

九、 __sleep(),執行serialize()時,先會調用這個(gè)函笑黑數

serialize() 函數會檢查類中(路到zhōng)是否存在一個(gè)魔術(shù)方法 事花__sleep()。如(rú)果存在,則該方法會優先被調妹黑用,然後才執行序列化操作。


此功能可(kě)以用于清理對象,并返回一個(gè)微醫包含對象中(zhōng)所有應被序列化的變量名稱的數組。


如(rú)果該方法未返回任何内容,則 NULL 被序列化,并産生一個秒如(gè) E_NOTICE 級别的錯誤。


注意:


__sleep() 不能返回父類的私有成員的名字。這樣做會産生一個(gè)雨商 E_NOTICE 級别的錯誤。可(kě)西到以用 Serializable 接口來替代。

作用:


__sleep() 方法常用于提交未提交的數據,或類似的清理操師要作。同時,如(rú)果有一些很大的對象,但不需要全部保存,這個(g問有è)功能就很好用。

具體請參考如(rú)下(xià)代碼:


<?php

class Person

{

    public $sex;

    public $name;

    public $a事計ge;


    public func錯樹tion __construct($name=&quo也低t;",  $age=25, $sex='男(ná黃山n)')

    {

        $thi你見s->name = $name;

      &草房nbsp; $this->age&nbs了著p; = $age;

      &n兵熱bsp; $this->sex  = $sex和靜;

    }


    /**

     * @return arra畫坐y

     */

    public function __sleep(森票) {

      &n不懂bsp; echo "當在類外部使用s員懂erialize()時會調用這裡的__sleep()方法
";

       個花 $this->name = base64_en校雨code($this->name)跳還;

        return arr冷醫ay('name', 'age數玩'); // 這裡必須返回一個(gè)數數村值,裡邊的元素表示返回的屬性名稱

    }

}


$person = new Person(亮身9;小明'); // 初始賦值

echo serialize($person);

echo '
';

代碼運行結果:


當在類外部使用serialize()時會調用這裡的__sleep()方法

O:6:"Person":2:{s:4:&的就quot;name";s:8:"了人;5bCP5piO";s:3:"綠可;age";i:25;}

十、 __wakeup(),執行unserialize()時,先習慢會調用這個(gè)函數

如(rú)果說 __sleep() 是白的,那麼 __wakeup() 就市高是黑的了。


那麼為什麼呢(ne)?


因為:


與之相反,`unserialize()` 會檢查是否存在一個(gè) 城習`__wakeup()` 方法。如(rú)果存在,則會窗裡先調用 `__wakeup` 方法,預先準備對暗慢象需要的資(zī)源。

作用:


__wakeup() 經常用在反序列化操作中房那(zhōng),例如(rú)重新建立數據庫連接,或執行話木其它初始化操作。

還是看代碼:


<?php

class Person

{

    public $sex;能員

    public $na家友me;

    public $age;舊你


    public function _船影_construct($name="",&n姐為bsp; $age=25, $sex='男(n自問án)')

    {

        $this->照拿name = $name;

     照煙   $this->age  = $age;

        $this-的很>sex  = $sex;筆劇

    }


    /**

     * @return arra到紙y

     */

    public年了 function __sleep() {

       購著 echo "當在類外部使用seria化河lize()時會調用這裡的__sleep()方法
";

        $this-&時人gt;name = base64_encode($this-&風就gt;name);

       拍答 return array('name', &多弟#39;age'); // 這裡必須爸刀返回一個(gè)數值,裡邊的元素表示返回的屬性名稱

    }


    /**

     * __放歌wakeup

     */

    public function __wakeup民匠() {

      &空作nbsp; echo "當在類外部銀日使用unserialize()時會調用這裡的_玩書_wakeup()方法
";

      &nbs愛有p; $this->name = 2;

      &低海nbsp; $this->sex 務工= '男(nán)';

      &nbs在看p; // 這裡不需要返回數組

    }

}


$person = new Person('小明費計'); // 初始賦值

var_dump(serialize($person));

var_dump(unserialize(serialize($per微短son)));

運行結果:


當在類外部使用serialize()時會調用這裡的__sleep()年場方法

string(58) "O:6:"Pers跳花on":2:{s:4:"name";s:8:鄉化"5bCP5piO"高紅;s:3:"age";i:男請25;}" 當在類外部使用serialize()時唱書會調用這裡的__sleep()方法

當在類外部使用unserialize()時會調用這裡的__w紅裡akeup()方法

object(Person)#2 (3) { ["sex&qu美做ot;]=> string(3) "男(nán)鐵務" ["name"]=> int(2吃現) ["age"]=> int志輛(25) }

十一、 __toString(),類被當成來北字符串時的回應方法

作用:


__toString() 方法用于一個(gè)銀北類被當成字符串時應怎樣回應。例如(rú) `echo $obj;月門` 應該顯示些什麼。

注意:


此方法必須返回一個(gè)字符串,否則将發出一條 司拿`E_RECOVERABLE_ERROR` 級别的緻命錯誤。

警告:


不能在 __toString() 方法中(zhōng)抛出異常。這麼做會導緻緻道喝命錯誤。

代碼:


<?php

class Person

{

    public $sex;

    public $name;

    public 離體$age;


    public function __constr業朋uct($name="",&nb生裡sp; $age=25, $sex='男(nán)')慢拍

    {

      &n票呢bsp; $this->name = $name;

        $this-吧妹>age  = $age;

      &nbs木這p; $this->sex  = $sex;

    }


    public fu離技nction __toString()

    {

      &nb問到sp; return  '歌日;go go go';

    }

}


$person = new Person('小明'); // 音商初始賦值

echo $person;

結果:


go go go

那麼如(rú)果類中(zhōng)沒有 __toString() 這離費個(gè)魔術(shù)方法運行會發生什麼呢(ne房吧)?讓我們來測試下(xià):


代碼:


<?php

class Person

{

    public $sex藍聽;

    public $name;

    public $age;綠司


    public fun樹有ction __construct($name="&qu站不ot;,  $age=25, $sex=&新路#39;男(nán)')

    {

       來物; $this->name = $票愛name;

     身物   $this->age  = $age;

      &nbs和愛p; $this->sex  = $快費sex;

    }

    

}


$person = new Person('小明'一務;); // 初始賦值

echo $person;

結果:


Catchable fatal error: Object of c討那lass Person could not be converted t高數o string in D:\phpStudy\WWW\t年農est\index.php on lin裡短e 18

很明顯,頁面報了一個(gè)緻命錯誤,這是語法所不允許的。


十二、 __invoke(),調用函數的方式調用一雪月個(gè)對象時的回應方法

作用:


當嘗試以調用函數的方式調用一個(gè)對象時,__in街很voke() 方法會被自動(dòng)調用。

注意:


本特性隻在 PHP 5.3.0 及以上版本有效。

直接上代碼:


<?php

class Person

{

    public $sex;

    public $name;

    public $age;


    public function __cons站議truct($name="",  $a得區ge=25, $sex='男(nán村外)')

    {

        $th務計is->name = $name;

        $thi歌年s->age  = $ag車又e;

      &nbs作車p; $this->sex  = $sex;

    }


    public function農會 __invoke() {

        echo '這制黑可(kě)是一個(gè)對象哦'火機;

    }


}


$person = new Person(&#雪員39;小明'); // 初始賦值

$person();

查看運行結果:


這可(kě)是一個(gè)對象哦

當然,如(rú)果你(nǐ)執意要将對象當函數方法使用,那麼會得到下(xià)但文面結果:


Fatal error: Function na熱著me must be a string in D:\phpStudy冷分\WWW\test\index.php on國村 line 18

十三、 __set_state(),調用var_export()導農離出類時,此靜态方法會被調用。

作用:


自 PHP 5.1.0 起,當調用 var_export()明家 導出類時,此靜态方法會被自動(dòng)調用。

參數:


本方法的唯一參數是一個(gè)數組,其中(zh新上ōng)包含按 array('property' =&吃厭gt; value, ...) 格式排列的類學煙屬性。

下(xià)面我們先來看看在沒有加 __set路小_state() 情況按下(xià),代碼及運行結果如(rú)何:


上代碼:


<?php

class Person

{

    public $sex;

    public $name;

    public $age;


    public function __cons時商truct($name="", 話們; $age=25, $sex='男(nán)唱問')

    {

      &水哥nbsp; $this->name 資討= $name;

        見場$this->age  = $age;

      &nb遠友sp; $this->sex  =電我 $sex;

    }


}


$person = new Person('電時;小明'); // 初始賦值

var_export($person);

看結果:


Person::__set_state(arra物就y( 'sex' => '男(nán)&下大#39;, 'name' => '小明'得森;, 'age' => 25, ))

很明顯,将對象中(zhōng)的屬性都打印出來了


加了 __set_state() 之後:


繼續上代碼:


<?php

class Person

{

    public $se科西x;

    public $name去朋;

    public $劇話age;


    public通兵 function __construct($name=舞鐘"",  $離高age=25, $sex='男(nán)')

    {

        $this水相->name = $name;

       唱歌 $this->age  = $age;

        $this->術問;sex  = $sex;

    }


    public s火火tatic function __set_state($an_array歌白)

    {

      &nb靜讀sp; $a = new Person();大那

      &nb妹可sp; $a->name = $an_array['相數;name'];

        re服又turn $a;

    }


}


$person = new Person('電對小明'); // 初始賦值

$person->name = '小紅';

var_export($person);

繼續看結果:


Person::__set_state(array綠樹( 'sex' => 歌費9;男(nán)', 'name一那' => '小紅', 'ag市樂e' => 25, ))

十四、 __clone(),當對象複制完成時調用

在多數情況下(xià),我們并不需要完全複制一個(gè)對象來舞文獲得其中(zhōng)屬性。但有一個(gè)情況下(xià)确實需要知睡:如(rú)果你(nǐ)有一個(gè) GTK 窗口對象,該對象持有窗口相來道關(guān)的資(zī)源。你(nǐ)可(kě)能會想複制一雨很個(gè)新的窗口,保持所有屬性與原來的窗口相同,市紅但必須是一個(gè)新的對象(因為如(rú)果不是新的湖知對象,那麼一個(gè)窗口中(zhōng)的改變就會影響到計小另一個(gè)窗口)。還有一種情況:如(rú)果對象 A 中(zh些是ōng)保存着對象 B 的引用,當你(nǐ)複制對象 A 時,你(nǐ)商音想其中(zhōng)使用的對象不再是對象 B 而是 B 的一個(gè)制影副本,那麼你(nǐ)必須得到對象 A 的一個(gè)副本。


作用:


對象複制可(kě)以通(tōng)過 clone 關(guān問還)鍵字來完成(如(rú)果可(kě)能,這将調用對象的 __cl冷謝one() 方法)。對象中(zhōng)的 __clone() 方法她師不能被直接調用。

語法:


$copy_of_object = clone $object;

注意:


當對象被複制後,PHP 5 會對對象的所有嗎都屬性執行一個(gè)淺複制(shallow copy)。音兵所有的引用屬性 仍然會是一個(gè)指向原來的變量的雨哥引用。


當複制完成時,如(rú)果定義了 __clone() 方法,則新創建的對象知答(複制生成的對象)中(zhōng)的 __clone() 方法會被調用,可(街校kě)用于修改屬性的值(如(rú)果有必要的麗公話)。

看代碼:


<?php

class Person

{

    public $個慢sex;

    public $n說民ame;

    public $age;


    public fu海動nction __construct($name=術錯"",  $a錢資ge=25, $sex='男(nán)')

    {

        $this->裡間;name = $name;

      有為  $this->age&n地地bsp; = $age;

        $this->們我sex  = $sex;

    }


    public functio做大n __clone()

    {

        echo __ME來黑THOD__."你(nǐ)正在克隆對風村象
";

    }


}


$person = new Person('小明'); // 事子初始賦值

$person2 = clone $person;


var_dump('persion1外下:');

var_dump($person);

echo '
';

var_dump('persion2:');

var_dump($person2);

看結果:


Person::__clone你(nǐ)正在克隆對象中資

string(9) "persion1:"湖錢 object(Person)#1 (3) 說文{ ["sex"]=北車> string(3) "聽些男(nán)" ["name"內為;]=> string(6) "小明&qu我亮ot; ["age"]=> in民個t(25) } 

string(9) "persion工兒2:" object(Person)#2 (3市黑) { ["sex"海樹]=> string(3) "男(nán)地和" ["name&qu大愛ot;]=> string(6) "小明" [制關"age"]=> int(25) }

克隆成功。


十五、__autoload(),嘗試加載未定義信城的類

作用:


你(nǐ)可(kě)以通(tōng)過定義這個(gè)函數來啟用類的自動(d的友òng)加載。

在魔術(shù)函數 __autoload() 方對門法出現以前,如(rú)果你(nǐ)要在一個(gè術輛)程序文(wén)件中(zhōng)實例化100個(gè)對象,跳大那麼你(nǐ)必須用include或者require包含進來100個(gè玩城)類文(wén)件,或者你(nǐ)把這100個國費(gè)類定義在同一個(gè)類文(wén)件中(z海山hōng) —— 相信這個(gè)文(wén)件一定會年日非常大,然後你(nǐ)就痛苦了。


但是有了 __autoload() 方法,以後就不必為此大傷腦筋了,工物這個(gè)類會在你(nǐ)實例化對象之前吧讀自動(dòng)加載制定的文(wén)件。


還是通(tōng)過例子(zǐ)來看看吧:


先看看以往的方式:


/** 

 * 文(wén)件non_autoload.php 

 */ 

   

require_once('project/class/市拿A.php');  

require_once('project/是綠class/B.php');&nbs弟年p; 

require_once('project/class/C.php&#熱議39;);  

   

if (條件A) {  

    $a = new A();&nb近樹sp; 

    $b = new喝作 B();  

    $c = new C();&nbs分市p; 

    // … 業(yè)務邏輯&熱作nbsp; 

} else if (條件B) {  

    $a = newA場問();  

    $b = n用店ew B();  

    // … 業(yè)務邏輯 &nbs說科p;

}

看到了嗎?不用100個(gè),隻是3個(gè)看起來就有點煩了。而是子且這樣就會有一個(gè)問(wèn)題:如(rú)果腳本執行“條件B”這個(水聽gè)分支時,C.php這個(gè)文(wén)件其實沒有必要包含說慢。因為,任何一個(gè)被包含的文(wén)件,無論是否使用,均男年會被php引擎編譯。如(rú)果不使用,卻被編譯,這樣可(kě)以被視媽些作一種資(zī)源浪費。更進一步,如(rú錢知)果C.php包含了D.php,D.php包含了E.php。并且服湖大部分情況都執行“條件B”分支,那麼就會浪費一部分資(zī)源去編譯C.php舊麗,D.php,E.php三個(gè)“無用”的文(wén)件。


那麼如(rú)果使用 __autoload() 方式呢(ne美內)?


/** 

 * 文(wén)件autoload_demo商校.php 

 */ 

function  __aut紙木oload($className) {&n很木bsp; 

    $filePath = “proje樹光ct/class/{$className}.p習裡hp”;  

    if (is_reada請外ble($filePath)) {&nb聽動sp; 

        requir女月e($filePath);  

    }  

}  

   

if (條件A) {  

    $a = new 雨玩A();  

    $b = new B();&信子nbsp; 

    $c = new C();  的體

    // … 業(yè)務邏算她輯  

} else if (條件B) {  

    $a = newA();草服  

    $b = new B(); &nb煙身sp;

    // … 業(y樹討è)務邏輯  

}

ok,不論效率怎麼用,最起碼界面看起來舒服多了,沒北討有太多冗餘的代。


再來看看這裡的效率如(rú)何,我們分析下(xià):也見


當php引擎第一次使用類A,但是找不到時,會自動(dòng)調用 __aut朋音oload 方法,并将類名“A”作為參數傳入。所以,我們在司拿 __autoload() 中(zhōng)需要的做醫吧的就是根據類名,找到相應的文(wén)件,并包含進來,如(r朋日ú)果我們的方法也找不到,那麼php引擎就會報錯了。


注意:


這裡可(kě)以隻用require,因為一旦包含進來後,ph高如p引擎再遇到類A時,将不會調用__autoload,而是直接使用内存中(zhō能中ng)的類A,不會導緻多次包含。

擴展:


其實php發展到今天,已經有将 `spl_autoload_re用低gister` — 注冊給定的函數作為 __autolo秒計ad 的實現了,但是這個(gè)不在啊本文(wén)講解之内,有興趣可(kě暗船)以自行看手冊。

十六、__debugInfo(),打印所需調試醫河信息

注意:


該方法在PHP 5.6.0及其以上版本才可(kě)以話說用,如(rú)果你(nǐ)發現使用無效或者報錯,請查看啊你(nǐ)的版本我窗。

看代碼:


<?php

class C {

    private $prop;


    public function __con信到struct($val) {

        $this->友唱;prop = $val;

    }


    /**

     * @return ar地白ray

     */

    public function __debugIn冷男fo() {

        re計金turn [

      &我要nbsp;     內錢9;propSquared' => $this->prop習白 ** 2,

        ];答很

    }

}


var_dump(new C(42));

結果:


object(C)#1 (1) { [&quo雪志t;propSquared"]=> int(1764) 技放}

再次注意:


這裡的 `**` 是乘方的意思,也是在P吃著HP5.6.0及其以上才可(kě)以使用,詳情請查看P近熱HP手冊

總結

以上就是PHP中(zhōng)我了解到的魔術(s哥鄉hù)方法了,常用的包括 __set() __get() __aut窗內oload() 等應該熟悉,其他的了解也沒有飛哥關(guān)系,畢竟知識不怕多嘛。


好了,有興趣的或者我這裡沒有說明白的,可(kě)以參考農化啊官方文(wén)檔。