Php 在无脂肪映射器对象上使用计算属性(未从数据库检索)

Php 在无脂肪映射器对象上使用计算属性(未从数据库检索),php,fat-free-framework,Php,Fat Free Framework,我知道我可以在扩展\DB\SQL\Mapper的类中使用这样的方法: 然后,当调用时,该模型将有一个虚拟计算属性upperBody,它将保存数据库中body字段的大写值 但我仅限于底层数据库引擎在功能方面提供的功能 是否有可能像这样在飞行中使用这些字段: $this->stripped_tags = strip_tags($this->body); $this->mdlPost->upperTitle = strtoupper($this->mdlPost->

我知道我可以在扩展\DB\SQL\Mapper的类中使用这样的方法:

然后,当调用时,该模型将有一个虚拟计算属性upperBody,它将保存数据库中body字段的大写值

但我仅限于底层数据库引擎在功能方面提供的功能

是否有可能像这样在飞行中使用这些字段:

$this->stripped_tags = strip_tags($this->body);
$this->mdlPost->upperTitle = strtoupper($this->mdlPost->title);
当然假设数据库中有一个现有的body字段

如果没有,那么我将如何编写自己的过滤器以在模板中使用,从而使{{@post.body{124; strip_tags}}。。。或者例如{@post.body |摘录30}

我通过使用cast解决了这个问题:

然后在控制器中,我有如下代码:

$this->stripped_tags = strip_tags($this->body);
$this->mdlPost->upperTitle = strtoupper($this->mdlPost->title);
使用$this->mdlPost->paginate…,,,,查询数据库后。。。,。。。,。。。 和var_dumping,upperTitle是一个空字符串

修改2:在@ikkez的评论中建议

public function __construct(\DB\SQL $db)
    {
        $this->db = $db;
        parent::__construct($db, 'posts');

        $this->onload(function($self){
            $self->set('upper_title', strtoupper($self->get('title')));
        });
    }
同样,没有成功

在转储映射器对象后,这可能会有所帮助

因此,无论它是什么,它都是以adhoc的形式显示的,但作为映射器对象本身的属性,它是空的


我可以看到这个值为NULL,表达式就是这个值应该是什么。这就是为什么在模板中执行@post.upper_title时会得到空输出的原因,那么您将如何解决这个问题。正常情况下,表达式接受查询字符串,值是执行该查询的结果,但这里显然不是这样。

似乎最好的方法是在模板中定义自己的过滤器。对其进行了描述。如果您需要更多的代码,请随时告诉我。

似乎最好的方法是在模板中定义您自己的过滤器。对其进行了描述。如果您需要更多的代码,请随时通知我。

只需添加字段,即可在映射器中动态使用,作为类的属性,您应该能够动态使用它:

class ModelA extends \DB\SQL\Mapper {

  public $stripped_tags;

}

只需将要在映射器中动态使用的字段作为属性添加到类中,您应该能够动态使用它:

class ModelA extends \DB\SQL\Mapper {

  public $stripped_tags;

}
映射器的实现比我们想象的要复杂一点,而无需查看源代码。首先,您不应该尝试设置不存在的映射器字段,因为映射器实现将它们解释为需要由数据库引擎派生的虚拟字段。这也是值为NULL的原因。相反,您应该使用ikkez所说的真实类属性

暗示

Mapper->cast方法忽略类属性,因此如果想要使用它,也应该调整cast方法

定义虚拟字段也仅在查询数据库之前有效

解决方案

不要通过调用Mapper->set或设置Mapper->field=…来创建或更新虚拟字段,后者在内部调用Mapper->set

改为创建类属性

使用ONLOAD事件填充属性

片段

下面的代码段显示了如何使用ONLOAD触发器定义用于存储编程派生值的自定义类属性。可执行示例可从以下网址获得:

从数据库中读取:

$mapper = new TestMapper($sql);
for ($mapper->load(); !$mapper->dry(); $mapper->next()) {
    printf("title:       %s\n", $mapper->title);
    printf("upper_title: %s\n", $mapper->upper_title);
}
结果:

title:       Hello World
upper_title: HELLO WORLD
映射器的实现比我们想象的要复杂一点,而无需查看源代码。首先,您不应该尝试设置不存在的映射器字段,因为映射器实现将它们解释为需要由数据库引擎派生的虚拟字段。这也是值为NULL的原因。相反,您应该使用ikkez所说的真实类属性

暗示

Mapper->cast方法忽略类属性,因此如果想要使用它,也应该调整cast方法

定义虚拟字段也仅在查询数据库之前有效

解决方案

不要通过调用Mapper->set或设置Mapper->field=…来创建或更新虚拟字段,后者在内部调用Mapper->set

改为创建类属性

使用ONLOAD事件填充属性

片段

下面的代码段显示了如何使用ONLOAD触发器定义用于存储编程派生值的自定义类属性。可执行示例可从以下网址获得:

从数据库中读取:

$mapper = new TestMapper($sql);
for ($mapper->load(); !$mapper->dry(); $mapper->next()) {
    printf("title:       %s\n", $mapper->title);
    printf("upper_title: %s\n", $mapper->upper_title);
}
结果:

title:       Hello World
upper_title: HELLO WORLD

请参阅经修正的问题。谢谢。在这种情况下,您需要在尝试的加载事件中计算属性,但由于某些原因,这也不起作用。请参阅修改后的问题。谢谢。在这种情况下,您需要在尝试的加载事件中计算属性,但由于某些原因,这也不起作用。我可能无意中跳过的唯一一件事是,我忘记声明类属性。。其余的我都做了同样的事。我回家后再检查一下。ThxUnfortute我仍然得到$mapper->upper_title的一个空字符串,这与以前版本的有什么不同吗
一个框架,因为我还在3.5版上?同样关于你的框架:不要通过调用Mapper->set或设置Mapper->field=…来创建或更新虚拟字段,它在内部调用Mapper->set,文档中说:$self->source='bar';//由于名为'source'$self->set'source'、'bar'的受保护属性而失败;//工作-只需直接使用setter关于Mapper->set和Mapper->属性:我的答案可能写得更好。我试着说,如果要创建虚拟字段或更新现有列,应该只创建虚拟字段,只更新真实字段db列。如果您不想更新列,也不想创建虚拟db派生字段,那么您必须创建一个真实的类属性。我已经用标记3.5.0、3.5.1和v3.6.0测试了我的链接代码示例,当然还有master。我不得不为3.5.0手动插入测试记录,因为Mapper不想创建没有主键的记录。我更新了链接代码,使之与标签3.5.0兼容。上面的标题和每个测试版本一样:HELLO WORLD。我唯一可能无意中跳过的是,我忘了声明类属性。。其余的我都做了同样的事。我回家后再检查一下。Thxu不幸的是,我仍然得到$mapper->upper_title的空字符串,与以前版本的框架相比,它的工作方式是否有任何变化,因为我仍然在版本3.5上?同样关于你的:不要通过调用mapper->set或设置mapper->field=…来创建或更新虚拟字段,后者在内部调用mapper->set,这里的文档说明:$self->source='bar';//由于名为'source'$self->set'source'、'bar'的受保护属性而失败;//工作-只需直接使用setter关于Mapper->set和Mapper->属性:我的答案可能写得更好。我试着说,如果要创建虚拟字段或更新现有列,应该只创建虚拟字段,只更新真实字段db列。如果您不想更新列,也不想创建虚拟db派生字段,那么您必须创建一个真实的类属性。我已经用标记3.5.0、3.5.1和v3.6.0测试了我的链接代码示例,当然还有master。我不得不为3.5.0手动插入测试记录,因为Mapper不想创建没有主键的记录。我更新了链接代码,使之与标签3.5.0兼容。上面的标题是每个测试版本的预期:HELLO WORLD。