2012-01-03 90 views
42

如何從對象方法內的給定參數創建屬性?如何動態創建新屬性

class Foo{ 

    public function createProperty($var_name, $val){ 
    // here how can I create a property named "$var_name" 
    // that takes $val as value? 

    } 

} 

而且我希望能夠訪問屬性,如:

$object = new Foo(); 
$object->createProperty('hello', 'Hiiiiiiiiiiiiiiii'); 

echo $object->hello; 

而且是有可能,我可以讓物業公共/保護/私有?我知道,在這種情況下,它應該是公開的,但我可能要添加一些瑪姬方法來獲得保護性和東西:)


我想我找到了解決辦法:

protected $user_properties = array(); 

    public function createProperty($var_name, $val){ 
    $this->user_properties[$var_name] = $val; 

    } 

    public function __get($name){ 
    if(isset($this->user_properties[$name]) 
     return $this->user_properties[$name]; 

    } 

你認爲這是一個好主意?

回答

60

有兩種方法可以做到這一點。

一個,你可以直接從動態類之外創建屬性:

class Foo{ 

} 

$foo = new Foo(); 
$foo->hello = 'Something'; 

或者,如果你希望通過你的createProperty方法來創建屬性:

class Foo{ 
    public function createProperty($name, $value){ 
     $this->{$name} = $value; 
    } 
} 

$foo = new Foo(); 
$foo->createProperty('hello', 'something'); 
+0

謝謝。儘管我在課堂上需要它。這是一種很複雜的解釋,屬性實際上是網站管理員可以啓用/禁用的站點擴展的對象:)但是我會使用我的解決方案,我認爲最好將它們放在數組中。 – Alex 2012-01-03 02:33:04

+3

可以將它們設置爲私人或保護? – 2014-04-26 03:31:22

+0

像這樣設置屬性不允許我們將其設置爲私有或受保護,因爲它是從公開設置的。但是,您可以嘗試使用OOP魔術方法'__get()'和'__set()'。請參閱http://stackoverflow.com/questions/4713680/php-get-and-set-magic-methods – mauris 2014-04-26 05:17:15

5

物業超載是很慢的。如果可以的話,儘量避免它。另外重要的是實施其他兩種魔法:

__isset(); __unset();

如果你不想後來發現使用這些對象時對一些常見的錯誤「屬性」

下面是一些例子:

http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members

亞歷克斯評論後編輯:

您可以檢查兩種解決方案之間的時間差異(更改$ REPEAT_PLEASE)

<?php 

$REPEAT_PLEASE=500000; 

class a {} 

$time = time(); 

$a = new a(); 
for($i=0;$i<$REPEAT_PLEASE;$i++) 
{ 
$a->data = 'hi'; 
$a->data = 'bye'.$a->data; 
} 

echo '"NORMAL" TIME: '.(time()-$time)."\n"; 

class b 
{ 
     function __set($name,$value) 
     { 
       $this->d[$name] = $value; 
     } 

     function __get($name) 
     { 
       return $this->d[$name]; 
     } 
} 

$time=time(); 

$a = new b(); 
for($i=0;$i<$REPEAT_PLEASE;$i++) 
{ 
$a->data = 'hi'; 
//echo $a->data; 
$a->data = 'bye'.$a->data; 
} 

echo "TIME OVERLOADING: ".(time()-$time)."\n"; 
+0

我對__get/__set/__call有點沉迷。我實際上在每個班級中使用它們以在使用該類時獲得良好的API ......迄今爲止不需要__isset ..您可以提供一個鏈接或與某些與超載相關的基準測試的內容嗎? – Alex 2012-01-03 02:38:48

+0

不好意思,但__call真的很慢 – 2012-01-03 03:19:25

+0

顯示一些參考資料/證據表明「屬性超載很慢」。 – Pacerier 2014-10-07 17:06:17

4

使用語法:$對象 - > {$財產} 其中$屬性是一個字符串變量, $對象可以是這樣,如果它是類或任何實例對象內

活生生的例子:http://sandbox.onlinephpfunctions.com/code/108f0ca2bef5cf4af8225d6a6ff11dfd0741757f

class Test{ 
    public function createProperty($propertyName, $propertyValue){ 
     $this->{$propertyName} = $propertyValue; 
    } 
} 

$test = new Test(); 
$test->createProperty('property1', '50'); 
echo $test->property1; 

結果:50

+0

這是我正在尋找的答案,我已經是新的了,您可以引用之前沒有的對象中的屬性已被聲明... $ object-> example =「hello」;我更多地關注如何動態地將屬性添加到對象,同時還動態指定要調用屬性的內容。 – andmar8 2015-06-26 15:17:24

1

下面的例子是爲那些不想申報整個班級誰。

$test = (object) []; 

$prop = 'hello'; 

$test->{$prop} = 'Hiiiiiiiiiiiiiiii'; 

echo $test->hello; // prints Hiiiiiiiiiiiiiiii