十六個魔術方法

冬字差一人發表於2021-03-05
No.1 __construct()
定義:類的建構函式
解釋:物件建立後第一個被自動呼叫的方法,通常被用來執行一些有用的初始化任務,例如在建立物件時對成員屬性賦予初始值。
例子:
Class Person
{
    public $name;
    public $age;
    public $sex;

    public function __construct($name = '', $sex = '男', $age = 28) {
        $this->name = $name;
        $this->sex = $sex;
        $this->age = $age;
    }
}

注意:如果子類中定義了建構函式則不會呼叫其父類的建構函式。要執行父類的建構函式,需要在子類的建構函式中呼叫 parent::__construct()
NO.2 __destruct() [不常見]
定義:類的解構函式
解釋:與建構函式相反,在類銷燬之前執行一些操作,比如關閉檔案、釋放結果等。
例子:
主動呼叫 unset( $obj )
主動呼叫 $obj = NULL
程式自動結束
NO.3 __call()
定義:在物件中呼叫一個不存在的方法時 自動呼叫
解釋:為了避免當呼叫的方法不存在時產生錯誤,而意外的導致程式中止,可以使用 __call() 方法來避免。
NO.4 __callStatic()
定義:同上 不同在於呼叫靜態方法時 自動呼叫
NO.5 __get()
定義:可以在物件的外部獲取私有成員屬性的值
例子:
private $name;
function __construct($name="", $age=1)
{
    $this->name = $name;
}
public function __get($propertyName)
{   
    return $this->$propertyName;
}
// 通過Person類例項化的物件,並通過構造方法為屬性賦初值
$Person = new Person("小明", 60);
// 直接訪問私有屬性name,自動呼叫了__get()方法可以間接獲取
echo "姓名:" . $Person->name . "<br>";
No.6 __set()
定義:與__get()類似 為私有屬性賦值
例子:
public function __set($propertyName, $value)
{
    $this->$propertyName = $value;
}
No.7 __isset()
定義:在類外部 判斷屬性isset()
例子:
public function __isset($content) {
    echo "當在類外部使用isset()函式測定私有成員{$content}時,自動呼叫<br>";
    echo  isset($this->$content);
}
echo isset($person->name);
No.8 __unset()
定義:在類外部刪除私有變數時自動呼叫
No.9 __sleep()
定義:執行serialize時會被自動呼叫
例子:
public function __sleep()
{
    $this->name = base64_encode($this->name);
    return ['name', 'age'];
}
echo serialize($person);
No.10 __wakeup()
定義:與__sleep類似 在執行unserialize()時被自動呼叫
No.11 __toString()
定義:當類被當成字串輸出時如何響應 例如 echo $obj; 應該顯示些什麼。

注意:此方法必須返回一個字串,否則將發出一條 `E_RECOVERABLE_ERROR` 級別的致命錯誤。

警告:不能在 __toString() 方法中丟擲異常。這麼做會導致致命錯誤。
NO.12 __invoke()
定義:當嘗試以呼叫函式的方式呼叫一個物件生效
例子:
public function __invoke() {
    echo '拿我當函式用,我就會被自動呼叫';
}

$person = new Perseon();
$person();
No.13 __set_state()
定義:呼叫var_export匯出類時,該方法自動被呼叫。
No.14 __clone()
定義:當物件複製完成時呼叫
例子:
public function __clone()
{
    echo __METHOD__."你正在克隆物件<br>";
    $this->name = 'new name';
    $this->age = 18;
}
$copy_of_object = clone $object;
No.15 __autoload()
定義:嘗試載入未定義的類
例子:
function  __autoload($className) {  
    $filePath = “project/class/{$className}.php”;  
    // 判斷檔案是否可讀
    if (is_readable($filePath)) {  
        require($filePath);  
    }  
}  

if (條件A) {  
    $a = new A();  
    $b = new B();  
    $c = new C();  
    // … 業務邏輯  
} else if (條件B) {  
    $a = newA();  
    $b = new B();  
    // … 業務邏輯  
}
注意:這裡可以只用require,因為一旦包含進來後,php引擎再遇到類A時,將不會呼叫__autoload,而是直接使用記憶體中的類A,不會導致多次包含。

擴充套件:
<?php
class autoloader {
  public static $loader;
  public static function init() {
    if (self::$loader == NULL)
      self::$loader = new self ();
    return self::$loader;
  }
  public function __construct() {
    spl_autoload_register ( array ($this, 'model' ) );
    spl_autoload_register ( array ($this, 'library' ) );
  }
  public function model($class) {
    $class = preg_replace ( '/_model$/ui', '', $class );
    set_include_path ( get_include_path () . PATH_SEPARATOR . '/model/' );
    spl_autoload_extensions ( '.model.php' );
    spl_autoload ( $class );
  }
  public function library($class) {
    set_include_path ( get_include_path () . PATH_SEPARATOR . '/lib/' );
    spl_autoload_extensions ( '.library.php' );
    spl_autoload ( $class );
  }
}
//call
autoloader::init ();
?>
No.16 __debugInfo()
定義:列印所需除錯資訊
例子:
public function __debugInfo()
{
    return [
        'message' => "姓名:".$this->name . " 年齡:".$this->age
    ];
}

$person = new Person('tongfei', 28);
var_dump($person);
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章