PHP的重載及魔術方法

来源:http://www.cnblogs.com/ldw-blogs/archive/2017/11/01/7764969.html
-Advertisement-
Play Games

首先你要知道什麼是php的魔術方法,它不是變魔術的,如果你想學習變魔術來錯地方了哦! 定義:PHP 將所有以 __(兩個下劃線)開頭的類方法保留為魔術方法。所以在定義類方法時,除了上述魔術方法,建議不要以 __ 為首碼。 作用:利用模式方法可以輕鬆實現PHP面向對象中重載(Overloading即動 ...


首先你要知道什麼是php的魔術方法,它不是變魔術的,如果你想學習變魔術來錯地方了哦!

定義:PHP 將所有以 __(兩個下劃線)開頭的類方法保留為魔術方法。所以在定義類方法時,除了上述魔術方法,建議不要以 __ 為首碼。

作用:利用模式方法可以輕鬆實現PHP面向對象中重載(Overloading即動態創建類屬性和方法)

其實很多博客主已經寫過這些方法了、、、但是我還是要說一遍。。誰讓你來聽了呢,碼這麼多字也不容易看完再走吧!

1.__construct,__destruct
__constuct構建對象的時被調用;
__destruct明確銷毀對象或腳本結束時被調用;

class Foo {

    private $name;
    private $link;

    public function __construct($name) {
        $this->name = $name;
    }

    public function __destruct() {
        echo 'Destroying: ', $this->name, PHP_EOL;//PHP_EOL代表php的換行符
    }
}

 

打住,先安利一波重載的定義及使用方法:

定義:PHP所提供的"重載"(overloading)是指動態地"創建"類屬性和方法。(我們是通過魔術方法(magic methods)來實現的)

作用:當調用當前環境下未定義或不可見的類屬性或方法時,重載方法會被調用。後面將使用"不可訪問屬性(inaccessible properties)"和"不可訪問方法(inaccessible methods)"來稱呼這些未定義或不可見的類屬性或方法。

註意:所有的重載方法都必須被聲明為 public

 

2.__get、__set、__isset、__unset、__call、__callStatic  //為啥放一起呢?


__set當給不可訪問或不存在屬性賦值時被調用
__get讀取不可訪問或不存在屬性時被調用

__isset對不可訪問或不存在的屬性調用isset()或empty()時被調用
__unset對不可訪問或不存在的屬性進行unset時被調用

__call調用不可訪問或不存在的方法時被調用
__callStatic調用不可訪問或不存在的靜態方法時被調用

 

Example #1 使用 __get()__set()__isset() 和 __unset() 進行屬性重載

<?php
class PropertyTest {
     /**  被重載的數據保存在此  */
    private $data = array();

 
     /**  重載不能被用在已經定義的屬性  */
    public $declared = 1;

     /**  只有從類外部訪問這個屬性時,重載才會發生 */
    private $hidden = 2;

    public function __set($name, $value) 
    {
        echo "Setting '$name' to '$value'\n";
        $this->data[$name] = $value;
    }


    public function __get($name) 
    {
        echo "Getting '$name'\n";
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }

        $trace = debug_backtrace();
        trigger_error(
            'Undefined property via __get(): ' . $name .
            ' in ' . $trace[0]['file'] .
            ' on line ' . $trace[0]['line'],
            E_USER_NOTICE);
        return null;
    }



    /**  PHP 5.1.0之後版本 */
    public function __isset($name) 
    {
        echo "Is '$name' set?\n";
        return isset($this->data[$name]);
    }

    /**  PHP 5.1.0之後版本 */
    public function __unset($name) 
    {
        echo "Unsetting '$name'\n";
        unset($this->data[$name]);
    }

    /**  非魔術方法  */
    public function getHidden() 
    {
        return $this->hidden;
    }
}


echo "<pre>\n";

$obj = new PropertyTest;

$obj->a = 1;
echo $obj->a . "\n\n";

var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));
echo "\n";

echo $obj->declared . "\n\n";

echo "Let's experiment with the private property named 'hidden':\n";
echo "Privates are visible inside the class, so __get() not used...\n";
echo $obj->getHidden() . "\n";
echo "Privates not visible outside of class, so __get() is used...\n";
echo $obj->hidden . "\n";
?>

看完了嗎?好好看!


5.__sleep,__wakeup
__sleep當使用serialize時被調用,當你不需要保存大對象的所有數據時很有用

__wakeup當使用unserialize時被調用,可用於做些對象的初始化操作

<?php
class Connection 
{
    protected $link;
    private $server, $username, $password, $db;
    
    public function __construct($server, $username, $password, $db)
    {
        $this->server = $server;
        $this->username = $username;
        $this->password = $password;
        $this->db = $db;
        $this->connect();
    }
    
    private function connect()
    {
        $this->link = mysql_connect($this->server, $this->username, $this->password);
        mysql_select_db($this->db, $this->link);
    }
    
    public function __sleep()
    {
        return array('server', 'username', 'password', 'db');
    }
    
    public function __wakeup()
    {
        $this->connect();
    }
}
?>

 


6.__clone
進行對象clone時被調用,用來調整對象的克隆行為

<?php
class SubObject
{
    static $instances = 0;
    public $instance;

    public function __construct() {
        $this->instance = ++self::$instances;
    }

    public function __clone() {
        $this->instance = ++self::$instances;
    }
}

class MyCloneable
{
    public $object1;
    public $object2;

    function __clone()
    {
      
        // 強制複製一份this->object, 否則仍然指向同一個對象
        $this->object1 = clone $this->object1;
    }
}

$obj = new MyCloneable();

$obj->object1 = new SubObject();
$obj->object2 = new SubObject();

$obj2 = clone $obj;


print("Original Object:\n");
print_r($obj);

print("Cloned Object:\n");
print_r($obj2);

?>

 


7.__toString
當一個類被轉換成字元串時被調用

<?php
class SubObject
{
    static $instances = 0;
    public $instance;

    public function __construct() {
        $this->instance = ++self::$instances;
    }

    public function __clone() {
        $this->instance = ++self::$instances;
    }
}

class MyCloneable
{
    public $object1;
    public $object2;

    function __clone()
    {
      
        // 強制複製一份this->object, 否則仍然指向同一個對象
        $this->object1 = clone $this->object1;
    }
}

$obj = new MyCloneable();

$obj->object1 = new SubObject();
$obj->object2 = new SubObject();

$obj2 = clone $obj;


print("Original Object:\n");
print_r($obj);

print("Cloned Object:\n");
print_r($obj2);

?>

 

8.__set_state
當調用var_export()導出類時,此靜態方法被調用。用__set_state的返回值做為var_export的返回值。

<?php

class A
{
    public $var1;
    public $var2;

    public static function __set_state($an_array) // As of PHP 5.1.0
    {
        $obj = new A;
        $obj->var1 = $an_array['var1'];
        $obj->var2 = $an_array['var2'];
        return $obj;
    }
}

$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';

eval('$b = ' . var_export($a, true) . ';'); // $b = A::__set_state(array(
                                            //    'var1' => 5,
                                            //    'var2' => 'foo',
                                            // ));
var_dump($b);

?>

 

enmmm,我知道你記不住的。。這麼多誰記得住啊,好煩啊、、、別,這還沒講完呢,更多方法請參考PHP的官方文檔:http://php.net/manual/zh/,別打我,你自己去看吧,畢竟好東西還是要眾樂樂的!了;另外這些代碼你最好再編譯器中運行一邊,不然看完你估計和沒看一個樣2333 ····  

作者原創、轉載請註明出處


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • import java.util.HashMap;import java.util.Map;import java.util.Map.Entry;import java.util.Set; import javax.servlet.http.HttpServletRequest; public st ...
  • 點擊試聽課程 前言 點擊試聽課程 前言 很多自學編程的同學經常和我說想學一門語言自己到網上找一些教程看到一半就像背單詞背到ambulance一樣堅持不下去了....究其原因基本上都是:內容太多,太枯燥,專業術語聽不懂,學的不知道能幹嘛,學到一半就放棄了...確實從零學習編程是一個很枯燥的事,所以在想 ...
  • 用到查看當前目錄的完整路徑使用:pwd 物理路徑和連接路徑什麼鬼?沒明白暫時借鑒別人的記錄下 顯示當前目錄的物理路徑 pwd –P 1: [root@DB-Server init.d]# cd /etc/init.d 2: [root@DB-Server init.d]# pwd -P 3: /et ...
  • JSTL簡介 用的時候: ...
  • 我們可以通過這樣子的方式去理解apache的工作原理 1 單進程TCP服務(堵塞式) 這是最原始的服務,也就是說只能處理個客戶端的連接,等當前客戶端關閉後,才能處理下個客戶端,是屬於阻塞式等待 這種阻塞型自然不適合處理多客戶端的請求,於是有了改版 2 多進程服務 採取多進程處理多客戶端連接請求,對單 ...
  • 一、引用類型有哪些 類 介面 數組 枚舉 註解 以上五種為引用數據類型, 我們現在學了其中的兩種 使用new關鍵字創建出來的類型都是引用數據類型 二、什麼是地址傳遞 引用數據類型有兩塊存儲空間 一個在棧(Stack)中,一個在堆(heap)中。 棧中存放的是堆中的地址 當我們把引用類型當作參數傳遞時 ...
  • jvm 垃圾回收 註意 : 本系列文章為學習系列,部分內容會取自相關書籍或者網路資源,在文章中間和末尾處會有標註 垃圾回收的意義 它使得java程式員不再時時刻刻的關註記憶體管理方面的工作. 垃圾回收機制會自動的管理jvm記憶體空間,將那些已經不會被使用到了的"垃圾對象"清理掉",釋放出更多的空間給其他 ...
  • 說明 嚴格意義上這個純模版不算原創,但是已經是理解整理後的 (加入我的代碼風格) 因為當時開了好幾個網頁,找不到參考 (包括但不限於高精度演算法( =4),n進位轉m進位( =2),c++重載運算符( =3)) 了, 如果原作者 (內容主要是來自那個模版) 看到,可以聯繫我,我會在開頭加入參考鏈接 適 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...