Как создать новое свойство динамически - PullRequest
60 голосов
/ 03 января 2012

Как я могу создать свойство из заданного аргумента внутри метода объекта?

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

  }

Как вы думаете, это хорошая идея?

Ответы [ 4 ]

87 голосов
/ 03 января 2012

Для этого есть два метода.

Один, вы можете напрямую динамически создавать свойство вне класса:

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');
8 голосов
/ 03 января 2012

Перегрузка свойств очень медленная. Если можете, постарайтесь избежать этого. Также важно реализовать два других магических метода:

__ Исеть (); __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";
6 голосов
/ 28 апреля 2015

Используйте синтаксис: $ 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

5 голосов
/ 04 марта 2017

Следующий пример предназначен для тех, кто не хочет объявлять целый класс.

$test = (object) [];

$prop = 'hello';

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

echo $test->hello; // prints Hiiiiiiiiiiiiiiii
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...