这个问题与这一个有关,但我过于简化了我的实际问题。因此,我提出了一个分开的问题:
我有两张桌子。一个保持间隔,以天为单位,与名称相关联,如bimonthly = 15和其他列出的周期性动作,并与间隔相关联。
我想列出在纯SQL中很容易实现的下一个定期操作:
SELECT *, DATE_ADD(updated_at, INTERVAL days DAY) AS next_action
FROM periodic_actions
INNER JOIN intervals ON interval_id = intervals.id
HAVING next_action > NOW()这是我的桌子:
CREATE TABLE `intervals` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(45) NULL,
`days` INT NULL,
PRIMARY KEY (`id`));
CREATE TABLE `periodic_actions` (
`id` INT NOT NULL AUTO_INCREMENT,
`interval_id` INT NOT NULL,
`name` VARCHAR(45) NULL,
`updated_at` TIMESTAMP NOT NULL,
PRIMARY KEY (`id`));以及间隔期的内容:
+----+----------+------+
| id | name | days |
+----+----------+------+
| 1 | daily | 1 |
| 2 | monthly | 30 |
| 3 | annually | 365 |
+----+----------+------+我想以雄辩的方式构建同样的查询,在虚拟列next_action上使用next_action:
Action::orderBy('next_action', 'asc')
->where('next_action', '>', Carbon::now())
->get()我拥有的最接近的,我无法隐藏在我的模型是:
Action::join('intervals', 'interval_id', '=', 'intervals.id')
->select(['*', DB::RAW('DATE_ADD(updated_at, INTERVAL days DAY) AS next_action')])
->havingRaw(DB::RAW('next_action > NOW()'))->get();当然,我有一个基本模型:
class Action extends Model
{
protected $table = 'periodic_actions';
public function interval()
{
return $this->belongsTo(Interval::class);
}
}发布于 2019-02-06 14:56:03
解决方案1:使用全局范围将字段添加到select语句中
虚拟列的一个问题是,如果您不阻止它,就会尝试更新它们。您可以从$fillable数组中排除它,并在模型中使用全球范围添加虚拟列,如下所示:
protected static function boot()
{
parent::boot();
static::addGlobalScope('next_action', function (Builder $builder) {
$builder->addSelect(DB::raw('DATE_ADD(updated_at, INTERVAL days DAY) AS next_action'));
});
}您必须记住,这将将您的模型耦合到MySQL,因为您所使用的日期函数不会在像sqlite这样的数据库中工作。
解决方案2:使用MySQL视图
通常,当我有多个计算字段时,我所做的就是创建一个MySQL视图。使用所需的所有计算字段创建视图,然后可以为该视图创建一个新的雄辩模型,而不必担心查询作用域。
请注意,您当然不能在此模型上使用create/update/delete,但是如果您只是为了显示目的而使用该模型,那就没有问题了。
https://stackoverflow.com/questions/54556064
复制相似问题