首页 > 解决方案 > Laravel 虚拟列无法保存

问题描述

virtualAs我使用 Laravel列修饰符在我的数据库表中添加了几个虚拟列:

 $table->decimal('grand_total')->virtualAs( '(total_value + (total_value*tax_rate))');

基本上,它保留了一个 mysql 虚拟列,该列根据存储在另一列中的总额和税率自动计算总计。

然而,Laravel 似乎根本不适合虚拟列。保存记录时,它会尝试INSERTUPDATE虚拟列,这在 mySQL 中显然是不允许的。我找不到在 Eloquent 模型中配置更新或插入时实际写入数据库的字段的方法。

我尝试将字段添加到模型$hidden中,$appends但似乎没有任何效果。

查看插入的 Laravel 源代码(https://github.com/laravel/framework/blob/5.6/src/Illuminate/Database/Eloquent/Model.php#L733),它似乎只是插入了任何属性$this->attributes. 当从数据库中读取记录时,grand_total从表中读取字段并将其设置为属性,然后在保存记录后尝试再次写入。

有没有办法让这个 Laravel 停止尝试保存虚拟列?

标签: phpmysqllaravel

解决方案


这是我为解决您的问题而编写的一个快速特征,它将在保存之前过滤位于 $virtualFields 属性中的字段。它需要在保存后进行选择(刷新)以获取虚拟字段的新值。如果您不需要查询此虚拟字段,我强烈建议您改为使用 mutator。

trait HasVirtualFields 
{
     public function save(array $options = [])
     {
          if (isset($this->virtualFields)) {
              $this->attributes = array_diff_key($this->attributes, array_flip($this->virtualFields));
          }

          $return = parent::save($options);
          $this->refresh(); // Refresh the model for the new virtual column values
          return $return;
    }
}

class YourModel
{
    use HasVirtualFields;
    protected $virtualFields = ['grand_total'];
}

推荐阅读