【发布时间】:2018-04-06 12:30:12
【问题描述】:
this question 的答案解释说,Model Scopes 不打算返回任何东西,而是返回一个 Query Builder 实例,并且应该使用自定义 getter 来返回 Model 实例。
问题
在我的例子中,我有一个 User 和 Contract 模型,其中一个用户有很多合同。合同期限可能重叠,但在任何给定时间,只有最晚开始日期的合同才应被视为有效(例如,合同 1 从 2017-01-01 到 2017-07-31 和合同 2 从 2017-06-01 到 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(),而不传递其他参数并返回模型实例而不是构建器,并且每次都必须调用first()?
【问题讨论】:
-
为什么不在用户中创建一个像
public function currentContract() { return $this->contracts()->current()->first(); }这样的方法,那么你要做的就是$user->currentContract()!! -
我会按照@Maraboc 说的做。只需将该逻辑包装到一个方法中即可。 Laravel 拥有所有这些很酷的东西,比如访问器、修改器、作用域等等,但它们并不适用于所有场景。
-
我为那个案例添加了一个答案@ingkevin,这只是一个建议,但是当人们喜欢它时,为什么不把它作为答案;)
标签: php laravel laravel-5 eloquent