是否可以在虚拟列中使用当前日期?
这是我到目前为止所尝试的:
我创建了以下迁移。
Schema::create('contracts', function (Blueprint $table) {
$table->increments('id');
$table->date('expires_at');
$table->boolean('is_expired')->virtualAs('expires_at < CURRENT_DATE()');
});
以下查询中的哪些输出:
create table `contracts` (
`id` int unsigned not null auto_increment primary key,
`expires_at` date not null,
`is_expired` tinyint(1) as (expires_at < CURRENT_DATE())
) default character set utf8mb4 collate utf8mb4_unicode_ci
我收到的错误消息:
生成列的表达&#39; is_expired&#39;包含不允许的功能。
所以,我知道你不能这样使用虚拟列。还有其他方法可以生成此列吗?也许有触发器的东西?
因为我在这个项目中使用Laravel,所以我很满意PHP解决方案。
也许有一个选项可以将原始sql语句放在$appends
数组中?那也有帮助。只要我能执行WHERE is_expired = false
。
答案 0 :(得分:1)
You can add custom attributes to your Laravel models. You just need to create a getter:
class Contract extends Model {
public function getIsExpiredAttribute() {
return (Carbon::now() > $this->expires_at;
}
}
This way you can check whether a contract is expired by looking at the value of $contract->is_expired
.
If you want that value to be returned with your models from the controllers, you'll need to put that attribute in $appends
array:
class Contract extends Model {
protected $appends = ['is_expired'];
}
If you want to filter non-expired contracts, you'll need to compare the expiration date and current date in your query:
$nonExpiredContracts = Contract::whereRaw('expires_at <= NOW()')->get();
If you need to use this constraint in multiple places, you can create a local scope in your model to let you avoid code duplications and make syntax clearer. First define the local scope:
class Contract extends Model {
public function scopeNonExpired($query) {
$query->whereRaw('expires_at <= NOW()');
}
}
Now you can pick non-expired contracts with:
$nonExpiredContracts = Contract::nonExpired()->get();