如何在Laravel中查询模型范围之外的内容



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

但我不太确定它是否有效,它只是我想到的。

我希望我帮了你。

最新更新