2012-01-03 25 views
42

Come posso creare una proprietà da un determinato argomento all'interno del metodo di un oggetto?Come creare dinamicamente una nuova proprietà

class Foo{ 

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

    } 

} 

E io voglio essere in grado di accedere alla proprietà come:

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

echo $object->hello; 

Inoltre è possibile che avrei potuto fare il pubblico di proprietà/protetto/privato? So che in questo caso dovrebbe essere pubblico, ma mi può essere utile per aggiungere alcuni metodi Magik ottenere le proprietà protette e roba :)


Credo di avere trovato una soluzione:

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]; 

    } 

Sei pensi sia una buona idea?

risposta

60

Ci sono due metodi per farlo.

Uno, è possibile creare direttamente proprietà dinamicamente dall'esterno della classe:

class Foo{ 

} 

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

Oppure, se si desidera creare proprietà attraverso il metodo createProperty:

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

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

grazie. Ne ho bisogno all'interno della classe però. È un po 'complicato da spiegare, le proprietà sono in realtà oggetti che sono le estensioni del sito che l'amministratore del sito può abilitare/disabilitare :) Ma userò la mia soluzione, penso che sia meglio tenerle all'interno di un array. – Alex

+3

È possibile impostarli come privati ​​o protetti? –

+0

L'impostazione di proprietà come questa non ci consente di renderlo privato o protetto perché è impostato dal pubblico. Tuttavia, puoi provare a lavorare con i metodi magici OOP '__get()' e '__set()'. Vedi http://stackoverflow.com/questions/4713680/php-get-and-set-magic-methods – mauris

5

sovraccarico proprietà è molto lento. Se puoi, cerca di evitarlo. È importante anche implementare gli altri due metodi magici:

__isset(); __unset();

Se non si vuole trovare alcuni errori comuni in seguito quando si utilizzano questi oggetti "attributi"

ecco alcuni esempi:

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

modificato dopo Alex commento:

È possibile verificare le differenze di tempo tra entrambe le soluzioni (modificare $ 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

Sono un po 'dipendente da __get/__set/__call. Praticamente li uso in ogni classe per ottenere API belle quando uso quella classe ... Non ho bisogno di __isset fino ad ora ... Puoi fornire un link o qualcosa con alcuni benchmark relativi all'overloading? – Alex

+0

Ci scusiamo per le cattive notizie, ma __call è troppo lento –

+0

Mostra alcuni riferimenti/prove a "sovraccarico proprietà è lento". – Pacerier

4

Utilizzare la sintassi: $ oggetto -> {$ proprietà} dove $ proprietà è una stringa variabile e $ oggetto può essere questo se è all'interno della classe o qualsiasi oggetto istanza

esempio dal vivo: 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; 

Risultato: 50

+0

Questa è la risposta che stavo cercando, già nuova che puoi solo fare riferimento a proprietà in oggetti che non sono stati precedentemente stato dichiarato ... $ oggetto-> esempio = "ciao"; Mi è stato più dopo come si aggiunge dinamicamente la proprietà all'oggetto mentre si specifica dinamicamente ciò che si desidera chiamare la proprietà. – andmar8

1

L'esempio seguente è per coloro che non vogliono dichiarare un'intera classe.

$test = (object) []; 

$prop = 'hello'; 

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

echo $test->hello; // prints Hiiiiiiiiiiiiiiii 
Problemi correlati