this question的答案解释说,模型范围并不意味着返回任何内容,只能使用查询生成器实例和自定义getter来返回模型实例。
问题
在我的情况下,我有一个User
和Contract
模型,其中用户有很多合同。合同期可能会重叠,但在任何给定时间,只有具有最新开始日期的合同才应被视为有效(例如,从2017-01-01
到2017-07-31
的合同1和2017-06-01
的合同2到2017-12-31
,2017-07-01
应退回合同2)
当前解决方案
使用范围我总是要调用->first()
:
public function scopeByDate(Builder $query, $date) {
return $query->whereDate('start', '<=', $date)
->whereDate('end', '>=', $date)
->orderBy('start', 'desc');
}
public function scopeCurrent(Builder $query) {
return $this->scopeByDate($query, date('Y-m-d'));
}
...
$user->contracts()->byDate('some-date')->first();
$user->contracts()->current()->first();
(更糟糕?)替代解决方案
否则,我可以将byDate()
和current()
设为静态,接受Builder
(看起来对我不好)或User
(甚至更糟?)实例并手动传递像
public static function byDate(Builder $query, $date) {
return $query->whereDate(...)->whereDate(...)->orderBy(...)->first();
}
...
Contract::byDate($user->contracts(), 'some-date');
或
public static function byUserAndDate(User $user, $date) {
return $user->contracts()->where...->where...->orderBy(...)->first()
}
...
Contract::byUserAndDate($user, 'some-date');
问题
我是否可以通过某种方式直接在查询构建器(关系)上调用byDate()
或current()
,而不传递其他参数并返回模型实例而不是构建器并且必须调用{{ 1}}每次?
答案 0 :(得分:1)
对于您的情况,您可以将逻辑包装在User模型中的方法内,然后在需要时调用它而无需->first()
:
用户模型
public function currentContract() {
return $this->contracts()->current()->first();
}
public function contractByDate($date) {
return $this->contracts()->byDate($date)->first();
}
致电:
$user->contractByDate('some-date');
$user->currentContract();
干净整洁:)