Как я могу создать свойство из заданного аргумента внутри метода объекта?
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;
Также возможно, что я мог бы сделать собственность открытой / защищенной / частной? Я знаю, что в этом случае он должен быть общедоступным, но я могу добавить некоторые методы 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]; }
вы думаете, что это хорошая идея?
Для этого есть два метода.
Во-первых, вы можете напрямую создавать свойства динамически извне класса:
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');
Перегрузка объектов происходит очень медленно. Если можно, постарайтесь избежать этого. Также важно реализовать два других магических метода:
__isset (); __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";
Используйте синтаксис: $ 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
Следующий пример предназначен для тех, кто не хочет объявлять целый класс.
$test = (object) []; $prop = 'hello'; $test->{$prop} = 'Hiiiiiiiiiiiiiiii'; echo $test->hello; // prints Hiiiiiiiiiiiiiiii