【问题标题】:Scope-like function to return Model返回模型的类似作用域的函数
【发布时间】:2018-04-06 12:30:12
【问题描述】:

this question 的答案解释说,Model Scopes 不打算返回任何东西,而是返回一个 Query Builder 实例,并且应该使用自定义 getter 来返回 Model 实例。

问题

在我的例子中,我有一个 UserContract 模型,其中一个用户有很多合同。合同期限可能重叠,但在任何给定时间,只有最晚开始日期的合同才应被视为有效(例如,合同 1 从 2017-01-012017-07-31 和合同 2 从 2017-06-012017-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-&gt;contracts()-&gt;current()-&gt;first(); } 这样的方法,那么你要做的就是$user-&gt;currentContract() !!
  • 我会按照@Maraboc 说的做。只需将该逻辑包装到一个方法中即可。 Laravel 拥有所有这些很酷的东西,比如访问器、修改器、作用域等等,但它们并不适用于所有场景。
  • 我为那个案例添加了一个答案@ingkevin,这只是一个建议,但是当人们喜欢它时,为什么不把它作为答案;)

标签: php laravel laravel-5 eloquent


【解决方案1】:

对于您的情况,您可以将逻辑包装在 User 模型中的方法中,然后在需要时调用它,而无需 -&gt;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();

漂亮干净:)

【讨论】:

  • 我几乎有相同的想法,将 where 放在 User 模型的函数上,这对我来说似乎太耦合了。将 wheres 放在 Contract 范围内并从用户的方法中访问它是“干净整洁的”,让我觉得有点愚蠢。感谢您的提示:)
  • 乐于助人 ;)
猜你喜欢
  • 1970-01-01
  • 2012-06-21
  • 1970-01-01
  • 2018-04-06
  • 2022-07-22
  • 1970-01-01
  • 2021-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多