1. 程式人生 > >php 給 私有屬性賦值的 方法

php 給 私有屬性賦值的 方法

今天在看 composer 自動載入的原理的時候看見了一個 給例項化物件的私有屬性賦值的操作,特此記錄一下

一般我們都知道,在類的外部是沒有辦法為類的私有屬性賦值或者改變私有屬性的值的。如:

<?php
    class Animal {
        private static $cat = "cat";
        private $dog = "dog";
        public $pig = "pig";
    }
    echo (new Animal)->$dog;    //報錯

但是如果真的要想為Animal的物件例項的私有屬性重新賦值【當然改變私有屬性的值的情況很少見,說起看來這有一點點hack的意味了】,可以利用php的 閉包

來實現。

實現的demo

<?php

class Animal {
   private static $cat = "cat";
   private $dog = "dog";
   public $pig = "pig";
}

$animal = new Animal;

/* 
* 獲取Animal類靜態私有成員屬性
*/
$cat = static function() {
   return Animal::$cat;
};

/* 
* 獲取Animal例項私有成員屬性
*/
$dog = function() {
   return $this->dog;
};

/* 
* 獲取Animal例項公有成員屬性
*/
$newDog = function() { return $this->dog; }; /** * bind函式: * 引數1($closure) : 表示閉包函式 * 引數2($newthis): 你把這個匿名的方法是否放在一個例項中,如果放在例項中,這個引數就是一個例項,如果不放在例項中,那就放null。當你不放在例項中,也就是不存在$this。也就不能用$this(經試驗 為null時僅可呼叫 static 的變數) * 引數3($newscope): 相當於類和例項呼叫的區別,函式的作用域, 傳類表示靜態呼叫方式,內部可以“類名::屬性”的方式使用;例項表示例項呼叫方式,內部可以“->” */
$bindCat = Closure::bind($cat, null, new Animal());// 給閉包綁定了Animal例項的作用域,但未給閉包繫結$this物件 $bindDog = Closure::bind(function() use ($animal){// 給閉包綁定了Animal類的作用域,同時將Animal例項物件作為$this物件繫結給閉包 $animal->dog = 'a new dog'; }, null, 'Animal'); $bindNewDog = Closure::bind($newDog, $animal, $animal);// 將Animal例項物件作為$this物件繫結給閉包,保留閉包原有作用域 echo $bindCat(),'<br>';// 根據繫結規則,允許閉包通過作用域限定操作符獲取Animal類靜態私有成員屬性 echo $bindDog(),'<br>';// 根據繫結規則,允許閉包通過繫結的$this物件(Animal例項物件)獲取Animal例項私有成員屬性 echo $bindNewDog(),'<br>';// 根據繫結規則,允許閉包通過繫結的$this物件獲取Animal例項公有成員屬性

這裡改變例項物件的私有屬性值的要點是將例項物件通過 function() user (){} 的方式來把它引入到閉包中,因為閉包已經處於Animal(或說是例項物件)的作用域中,所以就可以訪問他私有屬性的值了

關於php閉包的bind函式的更多細節,可以參考一下這篇文章