1. 程式人生 > >PHP中的常見魔術方法功能作用及用法例項

PHP中的常見魔術方法功能作用及用法例項

概述

在面向物件程式設計中,PHP提供了一系列的魔術方法,這些魔術方法為程式設計提供了很多便利。PHP中的魔術方法通常以__(兩個下劃線)開始,並且不需要顯示的呼叫而是由某種特定的條件出發。這篇文章簡單總結了PHP中提供的魔術方法。

開始之前

在總結PHP的魔術方法之前先來定義兩個類,以便後邊示例使用:

複製程式碼程式碼如下:
<?php
class Device {
    public $name;           
    public $battery;        
    public $data = array(); 
    public $connection;     
 
    protected function connect() {
        $this->connection = 'resource';
        echo $this->name . ' connected' . PHP_EOL;
    }
 
    protected function disconnect() {
        $this->connection = null;
        echo $this->name . ' disconnected' . PHP_EOL;
    }
}
 
class Battery {
    private $charge = 0;
 
    public function setCharge($charge) {
        $charge = (int)$charge;
        if($charge < 0) {
            $charge = 0;
        }
        elseif($charge > 100) {
            $charge = 100;
        }
        $this->charge = $charge;
    }
}
?>

Device類有四個成員屬性和兩個成員方法。Battery類有一個成員屬性和一個成員方法。

建構函式和解構函式

建構函式和解構函式分別在物件建立和銷燬時被呼叫。物件被“銷燬”是指不存在任何對該物件的引用,比如引用該物件的變數被刪除(unset)、重新賦值或指令碼執行結束,都會呼叫解構函式。

__construct()

__construct()建構函式是目前為止最經常使用的函式。在建立物件時,可以在建構函式中做一些初始化工作。可以為建構函式定義任意多個引數,只要在例項化時傳入對應個數的引數即可。建構函式中出現的任何異常都會阻止物件的建立。

複製程式碼程式碼如下:
class Device {
   public function  __construct(Battery $battery, $name) {
       $this->battery = $battery;
       $this->name = $name;
       $this->connect();
    }
}

上面的示例程式碼中,Device類的建構函式為成員屬性賦值並且呼叫了connect()方法。

複製程式碼程式碼如下:
將建構函式宣告為私有方法,可以防止在類外部建立物件,這在單利模式中經常使用。

__desctruct()

解構函式通常在物件被銷燬時呼叫,解構函式不接收任何引數。經常在解構函式中執行一些清理工作,比如關閉資料庫連線等。

屬性過載(Property Overloading)

有一點需要注意的是:PHP中的”過載”與其他大多數語言的過載不是太一樣,雖然都實現了相同的功能。
屬性過載涉及到的兩個魔術方法主要是用來處理屬性訪問,定義了當我們嘗試訪問一個不存在(或不可訪問)的屬性時會發生什麼。

__get()

魔術方法__get()在我們嘗試訪問一個不存在的屬性時會被呼叫。它接收一個引數,該引數表示訪問屬性的名字,並且將該屬性的值返回。在上面的Device類裡,有一個data屬性,該屬性就在這裡就起了作用,如下面得程式碼:

複製程式碼程式碼如下:
class Device {
    public function  __get($name) {
         if(array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }
        return null;
    }
}

該魔術方法最常用的地方就是通過建立一個“只讀”的屬性來擴充套件訪問控制。在上面的Battery類中,有一個私有屬性$charge,我們可以通過__get()魔術方法將該屬性擴充套件為在類外部可讀但不能修改。程式碼如下:

複製程式碼程式碼如下:
class Battery {
    private $charge = 0;
 
    public function  __get($name) {
        if(isset($this->$name)) {
            return $this->$name;
        }
        return null;
    }
}

__set()

__set()魔術方法在我們嘗試修改一個不可訪問的屬性時會被呼叫,它接收兩個引數,一個表示屬性的名字,一個表示屬性的值。示例程式碼如下:

複製程式碼程式碼如下:
class Device {
    public function  __set($name, $value) {
        // use the property name as the array key
        $this->data[$name] = $value;
    }
}

__isset()

__isset()魔術方法在對一個不可訪問的屬性呼叫isset()方法時會被呼叫,它接收一個引數,表示屬性的名字。它應該返回一個布林值,用來表示該屬性是否存在。程式碼如下:

複製程式碼程式碼如下:
class Device {
    public function  __isset($name) {
        return array_key_exists($name, $this->data);
    }
}

__unset()

__unset()魔術方法在呼叫unset()函式銷燬一個不能訪問的屬性時會被呼叫,它接收一個引數,表述屬性的名字。

物件轉換為字串

有時候我們需要將物件以字串的形式表現出來。如果我們直接列印一個物件,那麼程式將會輸出一個錯誤資訊:PHP Catchable fatal error: Object of class Device could not be converted to string

__toString()

__toString()在我們將物件當作字串一樣使用時會被呼叫,它不接收任何引數。該方法允許我們定義物件的表現形式。程式碼如下:

複製程式碼程式碼如下:
class Device {
    public function  __toString() {
       $connected = (isset($this->connection)) ? 'connected' : 'disconnected';
       $count = count($this->data);
       return $this->name . ' is ' . $connected . ' with ' . $count . ' items in memory' . PHP_EOL;
    }
    ...
}

__set_state()(PHP 5.1)

靜態魔術方法__set_state(),在我們使用var_export()函式輸出物件時會呼叫該方法。var_export()函式用來將PHP變數轉換為PHP程式碼,它接收一個包含物件屬性值的關聯陣列作為引數。示例程式碼如下:

複製程式碼程式碼如下:
class Battery {
    //...
    public static function  __set_state(array $array) {
        $obj = new self();
        $obj->setCharge($array['charge']);
        return $obj;
    }
    //...
}

克隆物件

預設的,物件都是按引用傳值的。因此,在將一個物件賦值給另一個變數時,只是建立了指向該物件的一個引用,並沒有複製該物件。為了實現真正得複製一個物件,我們需要使用clone關鍵字。
這種“按引用傳遞”的策略同樣適用於包含在物件內部的物件。即使我們克隆了一個物件,在物件內部的任何物件都不會被克隆,因此最終的結果是兩個物件共享了同一個內部物件。示例程式碼如下:

複製程式碼程式碼如下:
$device = new Device(new Battery(), 'iMagic');
$device2 = clone $device;
 
$device->battery->setCharge(65);
echo $device2->battery->charge;
// 65

__clone()

__clone()魔術方法__clone()可以解決上面的問題。當對一個物件使用clone關鍵字時,該魔術方法會被呼叫。在這個魔術方法裡,我們可以實現任何子物件的克隆,程式碼如下:

複製程式碼程式碼如下:
class Device {
    ...
    public function  __clone() {
        // copy our Battery object
        $this->battery = clone $this->battery;
    }
    ...
}

物件序列化

序列化是講任意資料轉換為字串格式的過程。序列化通常用來將整個物件存入資料庫或寫入檔案中。當反序列化儲存的資料時,我們可以得到序列化之前的物件。但是,並不是所有得資料都可以被序列化,比如資料庫連線。幸運的是,有一個魔術方法可以幫我們解決這個問題。

__sleep()

魔術方法__sleep()在對一個物件序列化時(呼叫serialize())會被呼叫。它不接收任何引數,而且應該返回一個包含所有應該被序列化的屬性的陣列。在該魔術方法中,也可以執行一些其他操作。
有一點要注意的是,不要再該函式中進行任何的析構操作,因為這可能會影響正在執行的物件。

示例程式碼如下:

複製程式碼程式碼如下:
class Device {
    public $name;           
    public $battery;       
    public $data = array();
    public $connection;    
    //...
    public function  __sleep() {
        return array('name', 'battery', 'data');
    }
    //...
}

__wakeup()

魔術方法__wakeup()在對儲存的物件反序列化時會被呼叫。它不接收任何引數,也沒有任何返回值。可以用它來處理在序列化時丟失的資料庫連線或資源。程式碼如下:

複製程式碼程式碼如下:
class Device {
    //...
    public function  __wakeup() {
        // reconnect to the network
        $this->connect();
    }
    //...
}

方法過載

PHP還有兩個與成員方法相關的魔術方法__call()和__callStatic(),這兩個魔術方法類似於屬性過載方法。

__call()

魔術方法__call()在呼叫不存在或不可訪問的方法時會被呼叫。它接收兩個引數,一個是呼叫的方法的名字,一個是包含函式引數的陣列。我們可以使用這種方法呼叫子物件中得同名函式。

在這個例子中,要注意函式call_user_func_array(),這個函式允許我們動態呼叫一個命名的函式。

示例程式碼如下:

複製程式碼程式碼如下:
class Device {
    //...
    public function  __call($name, $arguments) {
        // make sure our child object has this method
        if(method_exists($this->connection, $name)) {
            // forward the call to our child object
            return call_user_func_array(array($this->connection, $name), $arguments);
        }
        return null;
    }
    //...
}

__callStatic()

魔術方法__callStatic()與__call()的功能一樣,唯一不同的是,該方法在嘗試訪問一個不存在或不可訪問的靜態方法時會被呼叫。示例程式碼如下:

複製程式碼程式碼如下:
class Device {
    //...
    public static function  __callStatic($name, $arguments) {
        // make sure our class has this method
        if(method_exists('Connection', $name)) {
            // forward the static call to our class
            return call_user_func_array(array('Connection', $name), $arguments);
        }
        return null;
    }
    //...
}

將物件作為函式

有時候我們會需要將物件作為函式使用。將物件作為函式使用,就像我們使用其他普通的函式一樣,可以傳參。

__invoke()(PHP 5.3)

魔術方法__invoke()在嘗試將物件作為函式使用時會被呼叫。在該方法中定義的任何引數,都將被作為函式的引數。示例程式碼如下:

複製程式碼程式碼如下:
class Device {
    //...
    public function __invoke($data) {
        echo $data;
    }
    //...
}
$device = new Device(new Battery(), 'iMagic');
$device('test');
// equiv to $device->__invoke('test')
// Outputs: test

其他:__autoload()

__autoload()方法並不是一個魔術方法,但是這個方法非常有用。但是,對著PHP版本的更新,該函式已經不建議使用,取而代之的是spl_auto_register()函式。

相關推薦

PHP常見魔術方法功能作用用法例項

概述 在面向物件程式設計中,PHP提供了一系列的魔術方法,這些魔術方法為程式設計提供了很多便利。PHP中的魔術方法通常以__(兩個下劃線)開始,並且不需要顯示的呼叫而是由某種特定的條件出發。這篇文章簡單總結了PHP中提供的魔術方法。 開始之前 在總結PHP的魔術方法

PHP常見魔術方法功能作用用法實例

obj 寫入文件 對象的引用 for 表現 最終 get() 動態 method 概述 在面向對象編程中,PHP提供了一系列的魔術方法,這些魔術方法為編程提供了很多便利。PHP中的魔術方法通常以__(兩個下劃線)開始,並且不需要顯示的調用而是由某種特定的條件出發。這篇文章簡

巧用PHP__get()魔術方法

獲取 function 變量 返回 lib 底層 lower php腳本 redis PHP中的魔術方法有很多,這些魔術方法可以讓PHP腳本在某些特定的情況下自動調用。比如 __construct() 每次實例化一個類都會先調用該方法進行初始化。這裏我們講一下__get()

PHP魔術方法總結

__construct, __destruct , __call,__get, __set, __isset, __unset , __sleep, __wakeup, __toString, __clone and __autoload魔術方法。 1、__get、__set這兩個方法是為在

PHP魔術方法和關鍵字

  PHP中的魔術方法總結 :__construct, __destruct , __call, __callStatic,__get, __set, __isset, __unset , __slee

PHP魔術方法魔術常量

魔術方法__construct()構造方法在例項化一個物件的時候,順便在類名的後面增加一些用括號括起來的引數列表(可以理解為構造方法的實參) __destruct()析構方法與構造方法是一對,構造方法是

總結2: PHP魔術方法及其應用場景

PHP中有一類特別的系統方法,它們統一以__開頭,使用語義清晰簡單,這類形式特殊、作用特殊的方法被稱為魔術方法。 常見的魔術方法有__construct()、__destruct()、__call()、__callStatic()、__get()、__set(

php魔術方法應用例項

<?php //獲取當前類名 echo __CLASS__ ; //當前函式名(confirm echo __FUNCTION__ ; //當前方法名 (bankcard::confirm) echo __METHOD__ ; //在P

java this() 和super()的作用用法

原文地址:http://www.cnblogs.com/hasse/p/5023392.html 一、This   Java關鍵字this只能用於方法體中。this只能在類中的非靜態方法中使用,靜態方法和靜態的程式碼塊中絕對不能出現this,並且this只和特定的物件關聯,而不和類關聯,同一個類的不同物件

PHP的面向對象OOP魔術方法

function 魔術 public 一、什麽是魔術方法:PHP為我們提供了一系列用__開頭的函數,這些函數無需自己手動調用,會在合適的時機自動調用,這類函數稱為魔術函數。例如:1function __construct(){} 在new一個新對象時自動調用此函數二、PHP中都有那些魔術方法,以及

PHP的面向物件OOP魔術方法

一、什麼是魔術方法: PHP為我們提供了一系列用__開頭的函式,這些函式無需自己手動呼叫,會在合適的時機自動呼叫,這類函式稱為魔術函式。 例如: function __construct(){} 在new一個新物件時自動呼叫此函式 二、PHP中都有那些魔術方法,以及它們的作用:

PHP常見的錯誤提示解決辦法

    在PHP程式的編寫過程中難免會出現一些小的錯誤,例如拼寫錯誤以及小的符號錯誤。在PHP執行過程中若遇到錯誤會給出相應的提示,如何快速看懂這些提示背後的問題,對PHP除錯能力的提高有很大幫助。現舉例如下:     我在PHP中編寫圖片驗證碼時,有個簡單的判斷, if(

java的構造方法的使用作用分析

java中構造方法是一個重要的概念,初學時有人會對此構造方法的使用特別是其作用不清楚,下面我就來談談我對java中構造方法的理解,有不對或不清楚的地方希望各位看官提出意見,謝謝! 一.構造方法的定義宣

phpsession和cookie的使用區別

網上商城 標識 禁止 bsp 身份驗證 main str 什麽 ets 1.cookie的使用 什麽是 Cookie? cookie 常用於識別用戶。cookie 是服務器留在用戶計算機中的小文件。每當相同的計算機通過瀏覽器請求頁面時,它同時會發送 cookie。通過

構造方法作用靜態方法與非靜態方法的區別

margin mar 靜態方法 pro pfx doc rdl ref blank 可X7巧蛹勞5P3剄固巡久6http://shufang.docin.com/rgenh624 1品rleg9p頓慰恍http://shequ.docin.com/ibyrd96376 4C

Python魔術方法

ans normal pla -i port ont 語法 整數 text 魔術方法就是一個類/對象中的方法,和普通方法唯一的不同時,普通方法需要調用!而魔術方法是在特定時刻自動觸發。 這裏列舉出幾個常用的魔術方法: 1.__init__ 初始化魔術方法 觸發時機:初始化對

Tomcat下webapps夾root文件夾作用如何發布項目至root文件夾

best font 去掉 需要 ont pps ref -s 技術分享 轉載請註明出處: tomcat的root文件夾下面默認是tomcat的管理程序,但是如果你把自己的web項目發布到root下面的話,你可以不通過項目名直接訪問你的項目,比如,你見了一個名為

Linux常見文件類型文件系統類型

文件類型 常用文件系統類型 Linux中常見的七種文件類型: - 普通文件d 目錄文件l 鏈接文件(指向另一個文件,類似於它的快捷方式)s 套接字文件b 塊設備文件,二進制文件c 字符設備文件p 命名管道文件 Linux常用文件系統類型:

php常用的魔術方法

存儲空間 關閉 spa ext 函數 屬性和方法 utf-8 isset method __construct:構造函數,一旦創建對象都就會自動調用 __call:當調用了未定義的方法時會自動觸發 __set:當給類外部不可訪問的屬性設置值時會自動觸發 __get:當獲取類

(轉)ASP.NET常見文件類型用途

bin 許可 程序集 授權 rac 查看 類關系 置配 執行 從入門導師那繼承來的習慣,也是加上自己的所謂經驗判斷,一直對WEB開發不太感冒,可惜呀,從業近二十年,還得從頭開始對付HTML、CSS、JS、ASPX,以前的經驗,用不上啦!!!先從好好學習ASPX開發入手吧!