概述
在物件導向程式設計中,php提供了一系列的魔術方法,這些魔術方法為程式設計提供了很多便利。php中的魔術方法通常以__(兩個下劃線)開始,並且不需要顯示的呼叫而是由某種特定的條件出發。這篇文章簡單總結了php中提供的魔術方法。
開始之前
在總結php的魔術方法之前先來定義兩個類,以便後邊示例使用:
複製** **如下:
<?php
class device
protected function disconnect()
}class battery
elseif($charge > 100)
$this->charge = $charge;}}
?>
device類有四個成員屬性和兩個成員方法。battery類有乙個成員屬性和乙個成員方法。
建構函式和析構函式
建構函式和析構函式分別在物件建立和銷毀時被呼叫。物件被「銷毀」是指不存在任何對該物件的引用,比如引用該物件的變數被刪除(unset)、重新賦值或指令碼執行結束,都會呼叫析構函式。
__construct()
__construct()建構函式是目前為止最經常使用的函式。在建立物件時,可以在建構函式中做一些初始化工作。可以為建構函式定義任意多個引數,只要在例項化時傳入對應個數的引數即可。建構函式中出現的任何異常都會阻止物件的建立。
複製** **如下:
class device
}上面的示例**中,device類的建構函式為成員屬性賦值並且呼叫了connect()方法。
複製** **如下:
將建構函式宣告為私有方法,可以防止在類外部建立物件,這在單利模式中經常使用。
__desctruct()
析構函式通常在物件被銷毀時呼叫,析構函式不接收任何引數。經常在析構函式中執行一些清理工作,比如關閉資料庫連線等。
屬性過載(property overloading)
有一點需要注意的是:php中的」過載」與其他大多數語言的過載不是太一樣,雖然都實現了相同的功能。
屬性過載涉及到的兩個魔術方法主要是用來處理屬性訪問,定義了當我們嘗試訪問乙個不存在(或不可訪問)的屬性時會發生什麼。
__get()
魔術方法__get()在我們嘗試訪問乙個不存在的屬性時會被呼叫。它接收乙個引數,該引數表示訪問屬性的名字,並且將該屬性的值返回。在上面的device類裡,有乙個data屬性,該屬性就在這裡就起了作用,如下面得**:
複製** **如下:
class device
return null;}}
該魔術方法最常用的地方就是通過建立乙個「唯讀」的屬性來擴充套件訪問控制。在上面的battery類中,有乙個私有屬性$charge,我們可以通過__get()魔術方法將該屬性擴充套件為在類外部可讀但不能修改。**如下:
複製** **如下:
class battery
return null;}}
__set()
__set()魔術方法在我們嘗試修改乙個不可訪問的屬性時會被呼叫,它接收兩個引數,乙個表示屬性的名字,乙個表示屬性的值。示例**如下:
複製** **如下:
class device
}__isset()
__isset()魔術方法在對乙個不可訪問的屬性呼叫isset()方法時會被呼叫,它接收乙個引數,表示屬性的名字。它應該返回乙個布林值,用來表示該屬性是否存在。**如下:
複製** **如下:
class device
}__unset()
__unset()魔術方法在呼叫unset()函式銷毀乙個不能訪問的屬性時會被呼叫,它接收乙個引數,表述屬性的名字。
物件轉換為字串
有時候我們需要將物件以字串的形式表現出來。如果我們直接列印乙個物件,那麼程式將會輸出乙個錯誤資訊:php catchable fatal error: object of class device could not be converted to string
__tostring()
__tostring()在我們將物件當作字串一樣使用時會被呼叫,它不接收任何引數。該方法允許我們定義物件的表現形式。**如下:
複製** **如下:
class device
...}
__set_state()(php 5.1)
靜態魔術方法__set_state(),在我們使用var_export()函式輸出物件時會呼叫該方法。var_export()函式用來將php變數轉換為php**,它接收乙個包含物件屬性值的關聯陣列作為引數。示例**如下:
複製** **如下:
class battery
//...
}轉殖物件
預設的,物件都是按引用傳值的。因此,在將乙個物件賦值給另乙個變數時,只是建立了指向該物件的乙個引用,並沒有複製該物件。為了實現真正得複製乙個物件,我們需要使用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
...}
物件序列化
序列化是講任意資料轉換為字串格式的過程。序列化通常用來將整個物件存入資料庫或寫入檔案中。當反序列化儲存的資料時,我們可以得到序列化之前的物件。但是,並不是所有得資料都可以被序列化,比如資料庫連線。幸運的是,有乙個魔術方法可以幫我們解決這個問題。
__sleep()
魔術方法__sleep()在對乙個物件序列化時(呼叫serialize())會被呼叫。它不接收任何引數,而且應該返回乙個包含所有應該被序列化的屬性的陣列。在該魔術方法中,也可以執行一些其他操作。
有一點要注意的是,不要再該函式中進行任何的析構操作,因為這可能會影響正在執行的物件。
示例**如下:
複製** **如下:
class device
//...
}__wakeup()
魔術方法__wakeup()在對儲存的物件反序列化時會被呼叫。它不接收任何引數,也沒有任何返回值。可以用它來處理在序列化時丟失的資料庫連線或資源。**如下:
複製** **如下:
class device
//...
}方法過載
php還有兩個與成員方法相關的魔術方法__call()和__callstatic(),這兩個魔術方法類似於屬性過載方法。
__call()
魔術方法__call()在呼叫不存在或不可訪問的方法時會被呼叫。它接收兩個引數,乙個是呼叫的方法的名字,乙個是包含函式引數的陣列。我們可以使用這種方法呼叫子物件中得同名函式。
在這個例子中,要注意函式call_user_func_array(),這個函式允許我們動態呼叫乙個命名的函式。
示例**如下:
複製** **如下:
class device
return null;
}//...
}__callstatic()
魔術方法__callstatic()與__call()的功能一樣,唯一不同的是,該方法在嘗試訪問乙個不存在或不可訪問的靜態方法時會被呼叫。示例**如下:
複製** **如下:
class device
return null;
}//...
}將物件作為函式
有時候我們會需要將物件作為函式使用。將物件作為函式使用,就像我們使用其他普通的函式一樣,可以傳參。
__invoke()(php 5.3)
魔術方法__invoke()在嘗試將物件作為函式使用時會被呼叫。在該方法中定義的任何引數,都將被作為函式的引數。示例**如下:
複製** **如下:
class device
//...
}$device = new device(new battery(), 'imagic');
$device('test');
// equiv to $device->__invoke('test')
// outputs: test
其他:__autoload()
__autoload()方法並不是乙個魔術方法,但是這個方法非常有用。但是,對著php版本的更新,該函式已經不建議使用,取而代之的是spl_auto_register()函式。
php魔術常量,魔術方法
魔術常量 1。line 返回檔案中的當前行號。2。file 返回檔案的完整路徑和檔名。如果用在包含檔案中,則返回包含檔名。自php4.0.2 起,file 總是包含乙個絕對路徑,而在此之前的版本有時會包含乙個相對路徑。3。function 返回函式名稱 php4.3.0 新加 自php5 起本常量返...
invoke 魔術 PHP 魔術方法
php 魔術方法 構造方法 construct 析構方法 destruct get 與 set unset call 和 callstatic sleep 和 wakeup clone tostring invoke set state debuginfo construct 這個方法應該是最常用的...
php魔術方法
php5魔術方法 魔術函式 1。construct 建構函式 例項化物件時被呼叫,當 construct和以類名為函式名的建構函式同時存在時,construct將被呼叫,另乙個不被呼叫。2。destruct 析構函式 當刪除乙個物件或物件操作終止時被呼叫 程式結束後物件就摧毀 永遠都是最後執行的。3...