类似于范围的函数返回Model

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

标签: php laravel laravel-5 eloquent

this question的答案解释说,模型范围并不意味着返回任何内容,只能使用查询生成器实例和自定义getter来返回模型实例。

问题

在我的情况下,我有一个UserContract模型,其中用户有很多合同。合同期可能会重叠,但在任何给定时间,只有具有最新开始日期的合同才应被视为有效(例如,从2017-01-012017-07-31的合同1和2017-06-01的合同2到2017-12-312017-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}}每次?

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

干净整洁:)