PHP中八個魔術方法詳解
一個模組一個模組的學習更有助於同學們記憶知識,以下是本站小編精心為大家整理的PHP中八個魔術方法詳解,希望對大家有所幫助!更多內容請關注應屆畢業生網!
前言PHP中把以兩個下劃線__開頭的方法稱為魔術方法(Magic methods),這些方法在PHP中充當了舉足輕重的作用。 魔術方法包括:
__construct(),類的建構函式
__destruct(),類的解構函式
__call(),在物件中呼叫一個不可訪問方法時呼叫
__callStatic(),用靜態方式中呼叫一個不可訪問方法時呼叫
__get(),獲得一個類的成員變數時呼叫
__set(),設定一個類的成員變數時呼叫
__isset(),當對不可訪問屬性呼叫isset()或empty()時呼叫
__unset(),當對不可訪問屬性呼叫unset()時被呼叫。
範例下面讓我們以例項的形式向大家講解下這幾個魔術方法時如何使用的。
一、 __construct(),類的建構函式
php中構造方法是物件建立完成後第一個被物件自動呼叫的方法。在每個類中都有一個構造方法,如果沒有顯示地宣告它,那麼類中都會預設存在一個沒有引數且內容為空的構造方法。
1、 構造方法的作用
通常構造方法被用來執行一些有用的初始化任務,如對成員屬性在建立物件時賦予初始值。
2、 構造方法的在類中的宣告格式
function __constrct([引數列表]){
方法體 //通常用來對成員屬性進行初始化賦值
}
3、 在類中宣告構造方法需要注意的事項
1、在同一個類中只能宣告一個構造方法,原因是,PHP不支援建構函式過載。
2、構造方法名稱是以兩個下畫線開始的__construct()
下面是它的例子:
1234567891011121314 | <?php
class Person
{
public $name ;
public $age ;
public $sex ;
/**
*顯示宣告一個構造方法且帶引數
*/
public function __construct( $name = "" , $sex = "男" , $age =22){ $this ->name= $name ; $this ->sex= $sex ; $this ->age= $age ;} /***say方法*/ public function say(){ echo "我叫:" . $this ->name. ",性別:" . $this ->sex. ",年齡:" . $this ->age;
}
} |
建立物件$Person1且不帶任引數
$Person1 = new Person();
echo $Person1->say(); //輸出:我叫:,性別:男,年齡:27
建立物件$Person2且帶引數“小明”
$Person2 = new Person("小明"); echo $Person2->say(); //輸出:我叫:張三,性別:男,年齡:27
建立物件$Person3且帶三個引數
$Person3 = new Person("李四","男",25); echo $Person3->say(); //輸出:我叫:李四,性別:男,年齡:25
二、__destruct(),類的解構函式
通過上面的講解,現在我們已經知道了什麼叫構造方法。那麼與構造方法對應的就是析構方法。
析構方法允許在銷燬一個類之前執行的一些操作或完成一些功能,比如說關閉檔案、釋放結果集等。
析構方法是PHP5才引進的新內容。
析造方法的宣告格式與構造方法 __construct() 比較類似,也是以兩個下劃線開始的方法 __destruct() ,這種析構方法名稱也是固定的。
1、 析構方法的宣告格式
1234 | function __destruct() { //方法體 } |
注意:解構函式不能帶有任何引數。
2、 析構方法的作用
一般來說,析構方法在PHP中並不是很常用,它屬類中可選擇的一部分,通常用來完成一些在物件銷燬前的清理任務。
舉例演示,如下:
12345678 | <?php class Person{
public $name ;
public $age ;
public $sex ;
public function __construct( $name = "" , $sex = "男" , $age =22){ $this ->name= $name ; $this ->sex= $sex ; $this ->age= $age ;} /***say說話方法*/ public function say(){ echo "我叫:" . $this ->name. ",性別:" . $this ->sex. ",年齡:" . $this ->age;} /***宣告一個析構方法*/ public function __destruct(){ echo "我覺得我還可以再搶救一下,我的名字叫" . $this ->name;}} $Person = new Person( "小明" );unset( $Person ); //銷燬上面建立的物件$Person |
上面的程式執行時輸出:
我覺得我還可以再搶救一下,我的名字叫小明
三、 __call(),在物件中呼叫一個不可訪問方法時呼叫。
該方法有兩個引數,第一個引數 $function_name 會自動接收不存在的方法名,第二個 $arguments 則以陣列的方式接收不存在方法的多個引數。
1、 __call() 方法的格式:
1234 | function __call(string $function_name , array $arguments ) {
//方法體 } |
2、 __call() 方法的作用:
為了避免當呼叫的方法不存在時產生錯誤,而意外的導致程式中止,可以使用 __call() 方法來避免。
該方法在呼叫的方法不存在時會自動呼叫,程式仍會繼續執行下去。
請參考如下程式碼:
12345678910111213141516171819202122232425262728293031 | <?php class Person {
function say()
{
echo "Hello,world!<br>" ;} /***宣告此方法用來處理呼叫物件中不存在的方法*/ function __call( $funName , $arguments ){ echo "你所呼叫的函式:" . $funName . "(引數:" ; //輸出呼叫不存在的方法名print_r($arguments);//輸出呼叫不存在的方法時的引數列表echo")不存在!<br>n";//結束換行}}$Person=newPerson();$Person->run("teacher");//呼叫物件中不存在的方法,則自動呼叫了物件中的__call()方法$Person->eat("小明","蘋果"); $Person ->say();
執行結果:
你所呼叫的函式:run(引數:Array([0]=>teacher))不存在!
你所呼叫的函式:eat(引數:Array([0]=>小明[1]=>蘋果))不存在!
Hello,world!
四、__callStatic(),用靜態方式中呼叫一個不可訪問方法時呼叫
此方法與上面所說的__call()功能除了__callStatic()是未靜態方法準備的之外,其它都是一樣的。
請看下面程式碼:
<?php class Person {
function say()
{
echo "Hello,world!<br>" ;} /***宣告此方法用來處理呼叫物件中不存在的方法*/ public static function __callStatic( $funName , $arguments ){ echo "你所呼叫的靜態方法:" . $funName . "(引數:" ; //輸出呼叫不存在的方法名print_r($arguments);//輸出呼叫不存在的方法時的引數列表echo")不存在!<br>n";//結束換行}}$Person=newPerson();$Person::run("teacher");//呼叫物件中不存在的`方法,則自動呼叫了物件中的__call()方法$Person::eat("小明","蘋果"); $Person ->say(); |
執行結果如下:
你所呼叫的靜態方法:run(引數:Array ( [0] => teacher ) )不存在!
你所呼叫的靜態方法:eat(引數:Array ( [0] => 小明 [1] => 蘋果 ) )不存在!
Hello, world!
五、 __get(),獲得一個類的成員變數時呼叫
在 php 物件導向程式設計中,類的成員屬性被設定為 private 後,如果我們試圖在外面呼叫它則會出現“不能訪問某個私有屬性”的錯誤。那麼為了解決這個問題,我們可以使用魔術方法 __get()。
魔術方法__get()的作用
在程式執行過程中,通過它可以在物件的外部獲取私有成員屬性的值。
我們通過下面的 __get() 的例項來更進一步的連線它吧:
1234567 | <?php class Person {
private $name ;
private $age ;
function __construct( $name = "" , $age =1){ $this ->name= $name ; $this ->age= $age ;} /***在類中新增__get()方法,在直接獲取屬性值時自動呼叫一次,以屬性名作為引數傳入並處理*@param$propertyName**@returnint*/ public function __get( $propertyName ){ if ( $propertyName == "age" ){ if ( $this ->age>30){ return $this ->age-10;} else { return $this -> $propertyName ;}} else { return $this -> $propertyName ;}}} $Person = new Person( "小明" ,60); //通過Person類例項化的物件,並通過構造方法為屬性賦初值echo"姓名:".$Person->name."<br>";//直接訪問私有屬性name,自動呼叫了__get()方法可以間接獲取echo"年齡:".$Person->age."<br>";//自動呼叫了__get()方法,根據物件本身的情況會返回不同的值 |
執行結果:
姓名:小明
年齡:50
六、 __set(),設定一個類的成員變數時呼叫
__set() 的作用:
__set( $property, $value )` 方法用來設定私有屬性, 給一個未定義的屬性賦值時,此方法會被觸發,傳遞的引數是被設定的屬性名和值。
請看下面的演示程式碼:
123456 | <?php
class Person
{
private $name ; private $age ;
function __construct( $name = "" , $age =1){ $this ->name= $name ; $this ->age= $age ;} /***在類中新增__get()方法,在直接獲取屬性值時自動呼叫一次,以屬性名作為引數傳入並處理*@param$propertyName**@returnint*/ public function __get( $propertyName ){ if ( $propertyName == "age" ){ if ( $this ->age>30){ return $this ->age-10;} else { return $this -> $propertyName ;}} else { return $this -> $propertyName ;}}} $Person = new Person( "小明" ,60); //通過Person類例項化的物件,並通過構造方法為屬性賦初值echo"姓名:".$Person->name."<br>";//直接訪問私有屬性name,自動呼叫了__get()方法可以間接獲取echo"年齡:".$Person->age."<br>";//自動呼叫了__get()方法,根據物件本身的情況會返回不同的值 |
執行結果:
我叫小紅,今年16歲了
七、 __isset(),當對不可訪問屬性呼叫isset()或empty()時呼叫
在看這個方法之前我們看一下isset()函式的應用,isset()是測定變數是否設定用的函式,傳入一個變數作為引數,如果傳入的變數存在則傳回true,否則傳回false。
那麼如果在一個物件外面使用isset()這個函式去測定物件裡面的成員是否被設定可不可以用它呢?
分兩種情況,如果物件裡面成員是公有的,我們就可以使用這個函式來測定成員屬性,如果是私有的成員屬性,這個函式就不起作用了,原因就是因為私有的被封裝了,在外部不可見。那麼我們就不可以在物件的外部使用isset()函式來測定私有成員屬性是否被設定了呢?當然是可以的,但不是一成不變。你只要在類裡面加上一個__isset()方法就可以了,當在類外部使用isset()函式來測定物件裡面的私有成員是否被設定時,就會自動呼叫類裡面的__isset()方法了幫我們完成這樣的操作。
__isset()的作用:當對不可訪問屬性呼叫 isset() 或 empty() 時,__isset() 會被呼叫。
請看下面程式碼演示:
1234567 | <?php class Person {
public $sex ;
private $name ;
private $age ;
public function __construct( $name = "" , $age =25, $sex = '男' ){ $this ->name= $name ; $this ->age= $age ; $this ->sex= $sex ;} /***@param$content**@returnbool*/ public function __isset( $content ){ echo "當在類外部使用isset()函式測定私有成員{$content}時,自動呼叫<br>" ; echo isset( $this -> $content );}} $person = new Person( "小明" ,25); //初始賦值echoisset($person->sex),"<br>";echoisset($person->name),"<br>";echoisset($person->age),"<br>"; |
執行結果如下:
1 // public 可以 isset()
當在類外部使用isset()函式測定私有成員name時,自動呼叫 // __isset() 內 第一個echo
1 // __isset() 內第二個echo
當在類外部使用isset()函式測定私有成員age時,自動呼叫 // __isset() 內 第一個echo
1 // __isset() 內第二個echo
八、 __unset(),當對不可訪問屬性呼叫unset()時被呼叫。
看這個方法之前呢,我們也先來看一下 unset() 函式,unset()這個函式的作用是刪除指定的變數且傳回true,引數為要刪除的變數。
那麼如果在一個物件外部去刪除物件內部的成員屬性用unset()函式可以嗎?
這裡自然也是分兩種情況:
1、 如果一個物件裡面的成員屬性是公有的,就可以使用這個函式在物件外面刪除物件的公有屬性。
2、 如果物件的成員屬性是私有的,我使用這個函式就沒有許可權去刪除。
雖然有以上兩種情況,但我想說的是同樣如果你在一個物件裡面加上__unset()這個方法,就可以在物件的外部去刪除物件的私有成員屬性了。在物件裡面加上了__unset()這個方法之後,在物件外部使用“unset()”函式刪除物件內部的私有成員屬性時,物件會自動呼叫__unset()函式來幫我們刪除物件內部的私有成員屬性。
請看如下程式碼:
12345678 | <?php class Person {
public $sex ;
private $name ;
private $age ;
public function __construct( $name = "" , $age =25, $sex = '男' ){ $this ->name= $name ; $this ->age= $age ; $this ->sex= $sex ;} /***@param$content**@returnbool*/ public function __isset( $content ){ echo "當在類外部使用isset()函式測定私有成員{$content}時,自動呼叫<br>" ; echo isset( $this -> $content );}} $person = new Person( "小明" ,25); //初始賦值echoisset($person->sex),"<br>";echoisset($person->name),"<br>";echoisset($person->age),"<br>"; |
執行結果:
當在類外部使用unset()函式來刪除私有成員時自動呼叫的
1當在類外部使用unset()函式來刪除私有成員時自動呼叫的