数据库中的计算字段-Laravel

Sri*_*opi 1 laravel

在数据库中存储计算字段的最佳实践是什么。

例如,假设一张桌子有高度,重量,体重指数等字段

用户输入身高体重值,并自动填写bmi字段。如何用表格实现。

bmi $ bmi的公式=体重/(身高*身高)

尝试了以下配置文件模型

protected $table = 'profiles';

protected $fillable = ['user_id', 'weight', 'height', 'dob', 'age', 'bmi'];

public function user(){
  return $this->belongsTo(User::class, 'user_id');
}

protected static function boot() {
  parent::boot();

  static::saving(function($model){
      $model->bmi = $model->weight / ($model->height * $model->height);
      $model->age = (date('Y') - date('Y',strtotime($model->dob)));
  });
}
Run Code Online (Sandbox Code Playgroud)

配置文件控制器

public function store(Request $request)
  {
      $profile = new Profile();
      $profile->weight = $request->get('weight');
      $profile->height = $request->get('height');
      $profile->dob = $request->get('dob');
      $profile->age;
      $profile->bmi;
      $profile->save();
      return back()->with('success', 'Your profile has been updated.');
  }
Run Code Online (Sandbox Code Playgroud)

但是我收到一个错误

Illuminate \ Database \ QueryException (42S22)
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'weight' in 'field list' (SQL: insert into `users` (`weight`, `height`, `dob`, `bmi`, `age`, `created_by`, `updated_by`, `updated_at`, `created_at`) values (60, 175, 1988-04-03, 0.0019591836734694, 30, 2, 2, 2018-03-08 20:06:02, 2018-03-08 20:06:02))
Run Code Online (Sandbox Code Playgroud)

cee*_*yoz 7

在数据库中存储计算字段的最佳实践是什么。

一般来说,不要。它是冗余的——您的数据库已经拥有计算它所需的所有信息,那么为什么还要存储冗余数据呢?

相反,在模型上放置一个访问器:

public function getBmiAttribute() {
    return ($this->weight / ($this->height * $this->height));
}
Run Code Online (Sandbox Code Playgroud)

然后您可以$this->bmi获取计算值。

如果必须将其存储在数据库中,请使用Eloquent 事件。您可能想参与该saving活动。


Ohg*_*why 5

您可以boot在模型的方法中执行此操作:

protected static function boot() {
    parent::boot();

    static::saving(function($model){
        $model->bmi = $model->weight / ($model->height * $model->height);
    }); 
}
Run Code Online (Sandbox Code Playgroud)


w5m*_*w5m 5

从 Laravel 5.3 和 MySQL 5.7 开始,您可以使用列修饰符 virtualAs并为 MySQLstoredAs创建VIRTUAL (在读取行时评估)STORED (在插入或更新行时评估和存储)生成列。

virtualAs我在下面的例子中使用了......

    Schema::create('results', function (Blueprint $table) {
        $table->bigIncrements('id');
        ...
        $table->time('predicted_time')->nullable()->default(NULL);
        $table->time('handicap')->nullable()->default(NULL);
        $table->time('finish_time')->nullable()->default(NULL);
        $table->time('actual_time')->virtualAs('TIMEDIFF(finish_time, handicap)');
        $table->time('offset')->virtualAs('TIMEDIFF(actual_time, predicted_time)');
        ...        
    });
Run Code Online (Sandbox Code Playgroud)