基于当前日期

时间:2017-10-12 08:34:25

标签: php laravel laravel-5 eloquent

是否可以在虚拟列中使用当前日期?

这是我到目前为止所尝试的:

我创建了以下迁移。

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

1 个答案:

答案 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();