Как динамически создавать новое свойство
Как я могу создать свойство из заданного аргумента внутри метода объекта?
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;
Также возможно, что я мог бы сделать свойство public/protected/private? Я знаю, что в этом случае он должен быть общедоступным, но я могу добавить некоторые методы magik, чтобы получить защищенные свойства и прочее:)
Думаю, я нашел решение:
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];
}
Как вы думаете, это хорошая идея?
Ответы
Ответ 1
Есть два способа сделать это.
Во-первых, вы можете напрямую создавать свойства динамически извне класса:
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');
Ответ 2
Перегрузка свойств происходит очень медленно. Если можно, постарайтесь избежать этого. Также важно реализовать два других магических метода:
__ Исеть();
__unset();
Если вы не захотите найти некоторые распространенные ошибки позже при использовании этих атрибутов объекта
Вот несколько примеров:
http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members
EDITED после комментария Alex:
Вы можете проверить себя на разницу во времени между обоими решениями (изменить $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";
Ответ 3
Используйте синтаксис: $object → {$ property} где $property - строковая переменная и $ object может быть таким, если он находится внутри класса или любого объекта экземпляра
Пример в реальном времени: 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
Ответ 4
Следующий пример предназначен для тех, кто не хочет объявлять целый класс.
$test = (object) [];
$prop = 'hello';
$test->{$prop} = 'Hiiiiiiiiiiiiiiii';
echo $test->hello; // prints Hiiiiiiiiiiiiiiii