你可以在PHP中动态创建实例属性吗?

Bra*_*ayn 59 php oop design-patterns class

有没有办法动态创建所有实例属性?例如,我想能够产生在构造函数中的所有属性,仍然能够访问它们的类实例化这样的后:$object->property.请注意,我想单独访问属性,而不是使用数组; 这是我想要的一个例子:

class Thing {
    public $properties;
    function __construct(array $props=array()) {
        $this->properties = $props;
    }
}
$foo = new Thing(array('bar' => 'baz');
# I don't want to have to do this:
$foo->properties['bar'];
# I want to do this:
//$foo->bar;
Run Code Online (Sandbox Code Playgroud)

更具体地讲,当我处理那些有大量的属性类别,我希望能够选择数据库中的所有列(代表属性),并从中创建实例属性.每个列值应存储在单独的实例属性中.

Udo*_*Udo 61

有点.有一些魔术方法允许您在运行时挂起自己的代码来实现类行为:

class foo {
  public function __get($name) {
    return('dynamic!');
  }
  public function __set($name, $value) {
    $this->internalData[$name] = $value;
  }
}
Run Code Online (Sandbox Code Playgroud)

这是动态getter和setter方法的一个示例,它允许您在访问对象属性时执行行为.例如

print(new foo()->someProperty);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,会打印出"动态!" 并且您还可以为任意命名的属性赋值,在这种情况下,将以静默方式调用__set()方法.__call($ name,$ params)方法对对象方法调用执行相同的操作.在特殊情况下非常有用.但大多数时候,你会得到:

class foo {
  public function __construct() {
    foreach(getSomeDataArray() as $k => $value)
      $this->{$k} = $value;
  }
}
Run Code Online (Sandbox Code Playgroud)

...因为大多数情况下,您需要的只是将数组的内容转储到相应命名的类字段中,或者至少在执行路径中的非常明确的位置.因此,除非您确实需要动态行为,否则请使用最后一个示例用数据填充对象.

这称为重载 http://php.net/manual/en/language.oop5.overloading.php

  • 它们将是公开的,据我所知,它们不可能在运行时将它们设为私有或受到保护.对于"私有"可见性,您可以声明私有数组类型字段,然后填充它."受保护"也是如此.最好保持尽可能简单,所以你可以引入一个名为$ this-> ds的私有数组,其中的字段可以通过$ this-> ds ['fieldname']之类的语句来处理.或者如果你想要真正的幻想,你将实现一个基本上包含数组功能的迷你类,所以你可以做一些像$ this-> myDatasetObject-> fieldname这样的东西. (5认同)
  • 我相信ReflectionMethod :: setAccessible可以帮助您更改方法的私有访问权限 (2认同)

Cha*_*rch 23

这完全取决于你想要的.你能动态修改这个吗?并不是的.但是,您可以动态创建对象属性,就像在该类的一个特定实例中一样吗?是.

class Test
{
    public function __construct($x)
    {
        $this->{$x} = "dynamic";
    }
}

$a = new Test("bar");
print $a->bar;
Run Code Online (Sandbox Code Playgroud)

输出:

动态

因此,在构造函数中动态创建了名为"bar"的对象属性.

  • 这也表明动态属性是公共的。 (2认同)

Car*_*son 7

您可以使用实例变量充当任意值的持有者,然后使用__get magic方法将它们检索为常规属性:

class My_Class
{
    private $_properties = array();

    public function __construct(Array $hash)
    {
         $this->_properties = $hash;
    }

    public function __get($name)
    {
         if (array_key_exists($name, $this->_properties)) {
             return $this->_properties[$name];
         }
         return null;
    }
}
Run Code Online (Sandbox Code Playgroud)


The*_*per 7

是的你可以.

class test
{
    public function __construct()
    {
        $arr = array
        (
            'column1',
            'column2',
            'column3'
        );

        foreach ($arr as $key => $value)
        {
            $this->$value = '';
        }   
    }

    public function __set($key, $value)
    {
        $this->$key = $value;
    }

    public function __get($value)
    {
        return 'This is __get magic '.$value;
    }
}

$test = new test;

// Results from our constructor test.
var_dump($test);

// Using __set
$test->new = 'variable';
var_dump($test);

// Using __get
print $test->hello;
Run Code Online (Sandbox Code Playgroud)

产量

object(test)#1 (3) {
  ["column1"]=>
  string(0) ""
  ["column2"]=>
  string(0) ""
  ["column3"]=>
  string(0) ""
}
object(test)#1 (4) {
  ["column1"]=>
  string(0) ""
  ["column2"]=>
  string(0) ""
  ["column3"]=>
  string(0) ""
  ["new"]=>
  string(8) "variable"
}
This is __get magic hello
Run Code Online (Sandbox Code Playgroud)

此代码将在构造函数中设置动态属性,然后可以使用$ this-> column访问它.使用__get和__set魔术方法来处理未在类中定义的属性也是一种好习惯.更多信息可以在这里找到.

http://www.tuxradar.com/practicalphp/6/14/2

http://www.tuxradar.com/practicalphp/6/14/3


src*_*der 7

为什么每个例子都如此复杂?

<?php namespace example;

error_reporting(E_ALL | E_STRICT); 

class Foo
{
    // class completely empty
}

$testcase = new Foo();
$testcase->example = 'Dynamic property';
echo $testcase->example;
Run Code Online (Sandbox Code Playgroud)