无法在 RedBean 中存储盒装模型?

Can't store boxed model in RedBean?

如何在 RedBean 中存储从 $bean->box() 返回的模型?

例如,下面的代码不起作用(它只是插入一个空行):

class Model_Comment extends RedBean_SimpleModel {
    public $message;
}

$bean = R::dispense('comment');
$model = $bean->box();
$model->message = "Testing";
R::store($model);

如果我使用 $model->unbox()->message = "Testing",它会起作用,但这可能很快就会变得烦人...

显然上面的代码只是一个例子,我可以在这里设置属性 message on $bean,但我希望能够装箱一个bean并传递它到其他方法。

这是它应该如何工作,还是我在这里遗漏了什么?

原来是 "gotcha" 在处理 PHP 的 "magic" getter- 和 setter 方法时引起的 __get()__set().

查看 RedBean_SimpleModel 的源代码,它实际上使用神奇的 __set() 方法在设置 属性 时更新其 bean。

这是问题,直接来自PHP documentation:

__set() is run when writing data to inaccessible properties.

__get() is utilized for reading data from inaccessible properties.

__isset() is triggered by calling isset() or empty() on inaccessible properties.

__unset() is invoked when unset() is used on inaccessible properties.

所以事实证明,__set() 永远不会被现有(可访问的)class 成员调用,即 public $message。所以我可以从 class 中删除所有 public 字段,这将解决问题,但是我会失去所有自动完成功能和我的 IDE.[= 中的 lint 检查23=]

所以我想出了这个解决方案:

class MyBaseModel extends RedBeanPHP\SimpleModel {


    public function __construct(){
        foreach( get_object_vars($this) as $property => $value ){
            if( $property != 'bean' )
                unset($this->$property);
        }
    }


}


class Model_Comment extends MyBaseModel {
    public $message;
}

这有效地从 class MyBaseModel 实例化时删除 all 成员变量,except $bean,这当然是 RedBeanPHP_SimpleModel 的重要组成部分。

现在我可以轻松地 subclass MyBaseModel 并在我的 subclass 模型中拥有我需要的所有 public 字段,原始问题中的代码将工作。