php 什么是魔法方法,PHP魔法方法/函數詳解

在php的語法中,有一些系統自帶的方法名,均以雙下划線開頭,它會在特定的情況下被調用。即所謂的魔法函數。它們在面向對向編程中起着至關重要的作用。所以個人覺得很有必要整理一下。下面就php的15個魔法函數做一個詳細整理:

1. __construct() 和 __destruct()

__construct() 對象初始化時會調用此方法(對於內核而言是指初始化完成后調用此方法).此方法用得比較多。__destruct() 當對象銷毀時會調用此方法.那么什么時候對象會銷毀呢?一是用戶主動銷毀對象,二是當程序結束時由引擎自動銷毀

class People {

protected $_alive;

public function __construct()

{

$this->_alive = true;

echo 'Birth'.PHP_EOL;

}

public function __destruct()

{

$this->_alive = false;

echo 'Die'.PHP_EOL;

}

}

//主動銷毀對象

$test = new Test();

unset($test);

sleep(1);

//程序完成后自動銷毀對象

$test = new Test();

sleep(1);

2. __get() 和 __set()

面向對象編程中使用頻率很高的兩個方法.當設置和獲取對象的屬性不允許訪問時性,此方法會被調用。一定注意是不存在或不允許被讀寫時才會被調用。

因此對於一個對象,其屬性不確定時,用這兩個方法效果很好。

__get($name) 獲取對象不存在的屬性或無法訪問的屬性時調用.$name表示要獲取的屬性名

__set($name, $value) 設置對象不存在的屬性或無法訪問的屬性時調用.$name表示要設置的屬性名,$value表示要設置的值.

//例如:我們可以構建一個不確定屬性的數據記錄類

class Record {

protected $_data;

public function __get($name)

{

if (isset($this->_data[$name])) {

return $this->_data;

}

return false;

}

public function __set($name, $value)

{

$this->_data = $value;

}

}

$record = new Record();

$record->name = 'andrew';

echo 'My name is '.$record->name.PHP_EOL;

3. __isset() 和 __unset()

這兩個方法用得比較少些。當調用方法isset()判斷對象是否存在某屬性, 調用unset()注銷某屬性時。且當這些屬性不存在或不可訪問時,會分別調用__isset()和__unset()方法

與前面的__get()和__set()略同。都是某屬性不存在或不可訪問時被調用

__isset($name) 當調用方法isset()方法判斷不可訪問的類屬性時調用.$name表示屬性名.

__unset($name) 當調用方法unset()方法刪除不可訪問的類屬性時調用.$name表示屬性名.

//例如:

class People {

public $name;

public $sex;

private $_age;

public function __construct($name, $sex, $age)

{

$this->name = $name;

$this->sex = $sex;

$this->_age = $age;

}

public function __isset($name)

{

echo 'The property '.$name.' not exists'.PHP_EOL;

}

public function __unset($name)

{

echo 'The property '.$name.' can not be unset'.PHP_EOL;

}

}

$people = new People('andrew', 'male', 28);

isset($people->name);

isset($people->real_name);

unset($people->_age);

4. __call() 和 __callStatic()

前面,我們發現,在獲取對象的屬性時,如果此屬性不存在會調用__get()方法。那么如果調用此對象的方法時,如果此方法不存在呢?php引擎會自動調用__call()方法。

同樣,如果調用的是靜態方法,且不存在時會調用__callStatic()方法。需要注意的是,__callStatic()使用時是一個靜態方法,且僅在php5.3以上版本才支持.

__call($method, $args) 調用對象方法不存在或不允許被調用時此方法會被調用。$method表示調用的方法名,$args表示調用的參數

__callStatic($method, $args) 調用對象的靜態方法不存在或不允許被調用時此方法會被調用。$method表示調用的方法名,$args表示調用的參數.

//例如:我們假定人只有跳走兩種行為

class People {

public function jump()

{

echo 'I can jump'.PHP_EOL;

}

public function walk()

{

echo 'I can walk'.PHP_EOL;

}

public function __call($method, $args)

{

echo 'I can not '.$method.PHP_EOL;

}

//此方法必須是靜態方法,且在php5.3版本下可用

public static function __callStatic($method, $args)

{

echo 'We can not'.$method.PHP_EOL;

}

}

$people = new People();

$people->jump();

$people->walk();

$people->fly();

People::fly();

5. __sleep() 和 __wakeup()

這兩個方法,咋一看,就是睡覺和喚醒嘛。那跟對象有什么關系?有時候該用的時候也想不起來。其實,我們簡單點記,在php中有一個讓對象睡覺的方法,叫searialize(),

它會將對象的各屬性序列化以方便保存起來。而unsearialize()方法是將保存的序列化的數據解開變成對象。也叫喚醒。相對應的,當睡覺時,php會調用__sleep()方法,它

的返回值必須是一個數組,表示需要保存的屬性項, 對於文件句柄,數據庫連接等資源類型的數據是不能被序列化保存的。同理喚醒對象時,php會調用__wakeup()方法,

但與__sleep()不同的是,它返回值為空。被保存的屬性都會被解開。那它有什么用呢?剛我們說了,searialize是不能保存資源的。那么喚醒時如果我們想用到這些資源怎么

辦?回答很肯定,重新創建?那在哪里創建合適呢?當然是__wakeup()方法里面,因為每次喚醒時都會調用此方法嘛。這下我們很清楚這兩個方法的用途了。

__sleep() 當調用searialize()方法時調用,返回值為數組,表示需要序列化的數據項.

__wakeup() 當調用unsearizlie()方法時調用。一般用來在喚醒時初始化資源對象.

//例如我們有一個用戶類,用戶名和性別都是類屬性。用戶的密碼存在文件中

Class User {

public $username;

public $sex;

public $passFile;

private $_password;

public function __construct($username, $sex, $passFile)

{

$this->username = $username;

$this->sex = $sex;

$this->passFile = $passFile;

$this->_password = file_get_contents($passFile);

}

public function getPassword()

{

return $this->_password;

}

public function __sleep()

{

return array(

'username', 'sex', 'passFile',

);

}

public function __wakeup()

{

$this->_password = file_get_contents($this->passFile);

}

}

$user = new User('andrew', 'male', 'pass.data');

$serializeData = serialize($user);

echo $serializeData.PHP_EOL;

$user = unserialize($serializeData);

echo $user->getPassword().PHP_EOL;

6. __toString()

當對象在需要轉換成字符串時,會調用此方法。例如,echo對象時,將對象強制轉換為string類型時, 用於字符串參數的函數中.注意:此方法的返回值必須為字符串。

//例如:

class Info {

public function __toString()

{

return "info";

}

}

$info = new Info();

echo $info.PHP_EOL;

echo md5($info).PHP_EOL;

echo (String) $info.PHP_EOL;

echo substr($info, 0, 2).PHP_EOL;

7. __clone()

此方法在復制對象時被調用。我們知道在php中.$a為一個對象,$b=$a時。$b為$a的引用。當$a發生改變時。$b也會隨之發生變化。那么為了使$b不發生變化,我們需要用$b=clone $a;

那么,當$a在調用clone的時候,引擎會自動調用__clone()方法

//例如:以下一個簡單的例子

class Data {

public $value;

public function __clone()

{

echo "Clone myself".PHP_EOL;

}

}

$data = new Data();

$data->value = 4;

$newData = clone $data;

$data->value = 5;

echo "The data value is: ".$data->value.PHP_EOL;

echo "The new data value is: ".$newData->value.PHP_EOL;

//對面向對象比較熟的同學,一定對單例模式不陌生。PHP做單例模式的時候要記住把clone方法給禁掉。因為在單例模式中,是不允許復制對象的。如下例

class OnlyOne {

//單例對象

private static $_instance;

//不允許外部和子類調用初始化方法

private function __construct()

{}

//不允許復制

public function __clone()

{

throw new Exception('Not allow to clone me');

}

//獲取單例對象

public static function getInstance()

{

if (self::$_instance != null) {

return self::$_instance;

}

self::$_instance = new self();

return self::$_instance;

}

}

$onlyOne = OnlyOne::getInstance();

$newOne = clone $onlyOne;

8.  __autoload()

autoload顧名思義就是自動加載。它主要用來自動加載類。那如何自動加載呢?我們都知道在php中,要使用另外一個文件中的類需要用require或include方法

(包括require_once和include_one)導入進來。那么如果我要使用的類未被導入,則引擎會自動調用__autoload()方法。利用此特性,當我們的類名和類文件有規律

地存放時,我們可以使用__autoload()方法,根據需導入的類名,讓程序自動導入文件。此函數在許多的MVC框架中起着重要的作用。

__autoload($name) $name表示需要自動導入的類名

//我們制訂規則類名以目錄名加下載線拼接而成。例如:類Model_Config_Xml表示Model/Config/Normal.php文件.我們如何實現自動加載

//有類文件Model/Config/Normal.php內包含類如下:

class Model_Config_Normal {

public function __construct()

{

echo "Init Model_Config_Normal".PHP_EOL;

}

}

function __autoload($name)

{

$classPath = str_replace('_', DIRECTORY_SEPARATOR, $name);

require_once("$classPath.php");

}

//此時將無需再require('Model/Config/Normal.php')

$config = new Model_Config_Normal();

9. __set_state()

這個方法用得不多。了解這個方法前,需要先知道var_export()函數,var_export()和var_dump()類似,輸出一個變量的字符串表示。他與var_dump的區別在於它的返回結果的是合法的

php代碼.此代碼可以被eval執行. 注意:此方法是一個靜態方法,且在php5.1以上版本才支持。

//例如:

class Test {

public $name;

public $age;

public static function __set_state($data)

{

$obj = new Test();

$obj->name = $data['name'];

$obj->age = $data['age'] + 1;

return $obj;

}

}

$test = new Test();

$test->name = 'andrew';

$test->age = 27;

$code =var_export($test, true);

echo $code.PHP_EOL;

eval('$new='.$code.';');

var_dump($new);

10. __invoke()

這個方法我剛開始接觸的時候,一眼望去,真看不出來它到底干嘛的。主要是不明白invoke是啥意思。后來查了字典才明白。意思是呼叫。英語差傷不起呀。

在php中這個方法用於,把對象當方法用的時候。此方法會被調用。很簡單。注意,此方法僅5.3以上版本支持。

class Invoke {

public function __invoke()

{

echo 'I can run'.PHP_EOL;

}

}

$invoke = new Invoke();

$invoke();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值