【问题标题】:How to create new property dynamically如何动态创建新属性
【发布时间】:2012-02-01 04:41:46
【问题描述】:

如何从对象方法中的给定参数创建属性?

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 吗?我知道在这种情况下它应该是公开的,但我可能想添加一些魔法方法来获取受保护的属性和东西:)


我想我找到了解决方案:
  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];

  }

你认为这是个好主意吗?

【问题讨论】:

    标签: php object properties


    【解决方案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');
    

    【讨论】:

    • 谢谢。不过,我在课堂上需要它。解释起来有点复杂,属性实际上是站点管理员可以启用/禁用的站点扩展对象 :) 但我会使用我的解决方案,我认为最好将它们保存在数组中。
    • 是否可以将它们设置为私有或受保护?
    • 我认为太阳是正确的。 $this->$name = $value; 这一行实际上应该是 $this->name = $value;
    • 或者$this->{$name} = $value;,不是吗?
    • 如果你想要一个动态属性名称,比如在这种情况下,我们想要 hello 属性,然后使用 $this->{$name} 而不是 $this->name 因为 $this->name 只会创建一个名称属性
    【解决方案2】:

    以下示例适用于那些不想声明整个类的人。

    $test = (object) [];
    
    $prop = 'hello';
    
    $test->{$prop} = 'Hiiiiiiiiiiiiiiii';
    
    echo $test->hello; // prints Hiiiiiiiiiiiiiiii
    

    【讨论】:

      【解决方案3】:

      属性重载非常慢。如果可以的话,尽量避免它。同样重要的是实现另外两个魔术方法:

      __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";
      

      【讨论】:

      • 我有点沉迷于 __get / __set / __call。在使用该类时,我实际上在每个类中都使用它们来获得很好的 API ... 到目前为止不需要 __isset .. 你能提供一个链接或一些与重载相关的基准吗?
      • 很抱歉这个坏消息,但 __call 也很慢
      • 显示一些关于“属性重载很慢”的参考/证据。
      • @Pacerier 使用我在答案中输入的基准代码并检查您自己的服务器上两种解决方案所花费的时间
      【解决方案4】:

      使用语法:$object->{$property} 其中 $property 是一个字符串变量,并且 $object 如果在类或任何实例对象中,则可以是 this

      现场示例: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

      【讨论】:

      • 这是我一直在寻找的答案,我已经知道您可以只引用以前未声明的对象中的属性... $object->example = "hello";我更关注如何将属性动态添加到对象,同时动态指定要调用的属性。
      猜你喜欢
      • 2018-07-03
      • 1970-01-01
      • 2014-07-07
      • 1970-01-01
      • 2010-10-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多