在Yii2中在运行时声明类属性

I have a class that extends from Yii2's Model and I need to declare a class public property in the constructor, but I'm hitting a problem.

When I call

class Test extends \yii\base\Model {
    public function __constructor() {
        $test = "test_prop";
        $this->{$test} = null; // create $this->test_prop;
    }
}

Yii tries to call, from what I understand, the getter method of this property, which of course doesn't exist, so I hit this exception.

Also, when I actually do $this->{$test} = null;, this method gets called.

My question is: Is there a way to declare a class public property in another way? Maybe some Reflexion trick?

You could override getter/setter, e.g. :

class Test extends \yii\base\Model
{
    private $_attributes = ['test_prop' => null];

    public function __get($name)
    {
        if (array_key_exists($name, $this->_attributes))
            return $this->_attributes[$name];

        return parent::__get($name);
    }

    public function __set($name, $value)
    {
        if (array_key_exists($name, $this->_attributes))
            $this->_attributes[$name] = $value;

        else parent::__set($name, $value);
    }
}

You could also create a behavior...

Try to set variable in init method.

Like this:

public function init() {
  $test = "test_prop";
  $this->{$test} = null; // create $this->test_prop;
  parent::init();
}

Ok, I received help from one of Yii's devs. Here is the answer:

class Test extends Model {
    private $dynamicFields;

    public function __construct() {
        $this->dynamicFields = generate_array_of_dynamic_values();
    }

    public function __set($name, $value) {
        if (in_array($name, $this->dynamicFields)) {
            $this->dynamicFields[$name] = $value;
        } else {
            parent::__set($name, $value);
        }
    }

    public function __get($name) {
        if (in_array($name, $this->dynamicFields)) {
            return $this->dynamicFields[$name];
        } else {
            return parent::__get($name);
        }
    }

}

Note that I'm using in_array instead of array_key_exists because the dynamicFields array is a plain array, not an associative one.

EDIT: This is actually wrong. See my accepted answer.