不能在 RedBean 中存储盒装模型?

Posted

技术标签:

【中文标题】不能在 RedBean 中存储盒装模型?【英文标题】:Can't store boxed model in RedBean? 【发布时间】:2017-01-31 09:54:03 【问题描述】:

如何在 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属性$bean,但我希望能够装箱一个bean并将它传递给其他方法。

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

【问题讨论】:

【参考方案1】:

事实证明,这是在处理 php 的“神奇”getter 和 setter 方法 __get()__set() 时出现的“陷阱”。

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

这是陷阱,直接来自PHP documentation:

__set() 在将数据写入不可访问的属性时运行。

__get() 用于从不可访问的属性中读取数据。

__isset() 通过在不可访问的属性上调用 isset() 或 empty() 来触发。

当 unset() 用于不可访问的属性时,会调用 __unset()。

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

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

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;

这在实例化MyBaseModel 时有效地从类MyBaseModel 中删除所有 成员变量,除了 $bean,这当然是RedBeanPHP_SimpleModel 的重要组成部分。

现在我可以轻松地继承 MyBaseModel 并在我的子类模型中拥有我需要的所有公共字段,并且原始问题中的代码可以正常工作。

【讨论】:

以上是关于不能在 RedBean 中存储盒装模型?的主要内容,如果未能解决你的问题,请参考以下文章

如何克隆存储盒装特征对象的结构?

不将 php-redbean 的属性保存到数据库

使用 Redbean PHP ORM 时,是不是必须在每个脚本中调用 R::freeze()?

从bean拆箱模型时RedBean返回null?

RedBean ORM ID 列

PHP ORM 最佳实践:从另一个对象类型中检索值: