在Laravel中,我们知道这里记录的作用域函数:https://laravel.com/docs/8.x/eloquent#local-作用域。
在我的项目中,我想查询所有活动文档,所以我创建了这个范围:
class Document extends Model {
//...
public function scopeActive($query)
{
return $query->whereNotIn('status', ['done', 'expired'])->orWhere(function($query) {
$query->whereIn('reviewed', ['pending', 'todo'])->whereNotNull('reviewed');
});
}
利用这个范围,你可以做这样的事情:$activeDocuments = Document::active()->get()
。所有不在此范围内的文件均视为已存档。
是否可以查询不在此范围内的所有文档?例如$notActiveDocuments = Document::notActive()->get();
我的查询相对复杂,考虑到未来的维护,我不喜欢"反向"写这个查询。
如果没有,实现"范围外"查询的最可靠和最可维护的方法是什么?
您应该将这些数组作为常量移动到模型中。这样,它将适用于两个范围
class Document extends Model {
const ACTIVE_SCOPE_EXCLUDED_DOCUMENT_STATUSES = ['done', 'expired'];
const ACTIVE_SCOPE_INCLUDED_DOCUMENT_REVIEW_STATUSES = ['pending', 'todo'];
public function scopeActive($query)
{
return $query->whereNotIn('status', self::ACTIVE_SCOPE_EXCLUDED_DOCUMENT_STATUSES)
->orWhere(function($query) {
$query->whereIn('reviewed', self::ACTIVE_SCOPE_INCLUDED_DOCUMENT_REVIEW_STATUSES)
->whereNotNull('reviewed'); // I think this is unnecessary
});
}
// reverse scope should look something like this
public function scopeNotActive($query)
{
return $query->whereIn('status', self::ACTIVE_SCOPE_EXCLUDED_DOCUMENT_STATUSES)
->where(function($query) {
$query->whereNotIn('reviewed', self::ACTIVE_SCOPE_INCLUDED_DOCUMENT_REVIEW_STATUSES)
->orWhereNull('reviewed'); // I think this is unnecessary
});
}
如果两种情况下的查询始终相同,我认为您可以用以下方式完成:
public function scopeActiveOrNotActive($query, $status, $reviewed)
{
return $query->whereNotIn('status', $status)
->orWhere(function($query) use ($reviewed) {
$query->whereIn('reviewed', $reviewed)
->whereNotNull('reviewed');
});
}
知道这两个变量将始终是一个数组,您只需这样做:
Document::activeOrNotActive(['foo', 'bar'], ['otherFoo', 'otherBar'])->get();
如果我想一想,我认为你可以这样做:
public function scopeActive($query, $status, $reviewed)
{
return $query->whereNotIn('status', $status)
->orWhere(function($query) use ($reviewed) {
$query->whereIn('reviewed', $reviewed)
->whereNotNull('reviewed');
});
}
public function scopeNotActive($query, $status, $reviewed)
{
return $query->active($status, $reviewed);
}
在完成之后:
Document::active(['foo', 'bar'], ['foo1', 'bar2'])->get();
Document::notActive([! 'foo', ! 'bar'], [! 'foo1', ! 'bar2'])->get();
但我不太确定它是否有效,它只是我想到的。
我希望我帮了你。