PHP魔術方法

做下記錄,溫故而知新。

構造函數和析構函數

__construct 構造函數
類會在每次創建新對象時先調用此方法,所以非常適合在使用對象之前做一些初始化工作。

__deconstruct
析構函數會在到某個對象的所有引用都被刪除或者當對象被顯式銷燬時執行。

<?php
class MyDestructableClass {
    public $name;
   function __construct() {
       print "In constructor\n";
       $this->name = "MyDestructableClass";
   }

   function __destruct() {
       print "Destroying " . $this->name . "\n";
   }
}

$obj = new MyDestructableClass();
?>

方法重載

public __call ( string $name , array $arguments ) : mixed
public static __callStatic ( string $name , array $arguments ) : mixed

在對象中調用一個不可訪問方法時,__call() 會被調用。

在靜態上下文中調用一個不可訪問方法時,__callStatic() 會被調用。

方法不存在時也會經過此函數,可以做特殊處理,比如實現一個redis操作類,絕大多數的操作方法可以直接從predis本身的,這時藉助__call很容易實現這樣的功能

屬性重載

public __set ( string $name , mixed $value ) : void
public __get ( string $name ) : mixed
public __isset ( string $name ) : bool
public __unset ( string $name ) : void

在給不可訪問屬性賦值時,__set() 會被調用。

讀取不可訪問屬性的值時,__get() 會被調用。

當對不可訪問屬性調用 isset() 或 empty() 時,__isset() 會被調用。

當對不可訪問屬性調用 unset() 時,__unset() 會被調用。

參數 $name 是指要操作的變量名稱。__set() 方法的 $value 參數指定了 $name 變量的值。

屬性重載只能在對象中進行。在靜態方法中,這些魔術方法將不會被調用。所以這些方法都不能被 聲明爲 static

屬性重載 當屬性不存在的時候也會進入魔術方法,可以在方法中做處理,比如依賴注入的setter使用

<?php
class PropertyTest {
     /**  被重載的數據保存在此  */
    private $data = array();

 
     /**  重載不能被用在已經定義的屬性  */
    public $declared = 1;

     /**  只有從類外部訪問這個屬性時,重載纔會發生 */
    private $hidden = 2;

    public function __set($name, $value) 
    {
        echo "Setting '$name' to '$value'\n";
        $this->data[$name] = $value;
    }

    public function __get($name) 
    {
        echo "Getting '$name'\n";
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }

        $trace = debug_backtrace();
        trigger_error(
            'Undefined property via __get(): ' . $name .
            ' in ' . $trace[0]['file'] .
            ' on line ' . $trace[0]['line'],
            E_USER_NOTICE);
        return null;
    }

    /**  PHP 5.1.0之後版本 */
    public function __isset($name) 
    {
        echo "Is '$name' set?\n";
        return isset($this->data[$name]);
    }

    /**  PHP 5.1.0之後版本 */
    public function __unset($name) 
    {
        echo "Unsetting '$name'\n";
        unset($this->data[$name]);
    }

    /**  非魔術方法  */
    public function getHidden() 
    {
        return $this->hidden;
    }
}


echo "<pre>\n";

$obj = new PropertyTest;

$obj->a = 1;
echo $obj->a . "\n\n";

var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));
echo "\n";

echo $obj->declared . "\n\n";

echo "Let's experiment with the private property named 'hidden':\n";
echo "Privates are visible inside the class, so __get() not used...\n";
echo $obj->getHidden() . "\n";
echo "Privates not visible outside of class, so __get() is used...\n";
echo $obj->hidden . "\n";
?>

__toString()
public __toString ( void ) : string
__toString() 方法用於一個類被當成字符串時應怎樣迴應。例如 echo $obj; 應該顯示些什麼。此方法必須返回一個字符串,否則將發出一條 E_RECOVERABLE_ERROR 級別的致命錯誤。

<?php
// Declare a simple class
class TestClass
{
    public $foo;

    public function __construct($foo) 
    {
        $this->foo = $foo;
    }

    public function __toString() {
        return $this->foo;
    }
}

$class = new TestClass('Hello');
echo $class;
?>

__invoke()
__invoke ([ $... ] ) : mixed
當嘗試以調用函數的方式調用一個對象時,__invoke() 方法會被自動調用。

  <?php
  class CallableClass 
  {
      function __invoke($x) {
          var_dump($x);
      }
  }
  $obj = new CallableClass;
  $obj(5);
  var_dump(is_callable($obj));
  ?>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章