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.