如何使用 laravel-model-status 包按 Laravel 中的最新状态进行过滤?
How to filter by latest status in Laravel using laravel-model-status package?
当前系统:
我正在使用 Laravel 和 Spatie 包 laravel-model-status
.
需要:
以下是我正在寻找的正式描述:
Get a list of users whose latest status in set S is the status T.
基本上,我正在寻找一个 Eloquent 可以变成本地范围的示例 scopeLatestStatusEquals($T, ...$setS)
。
这是它的用法:
// Set of statuses to check for latest status:
$setS = ['status 1', 'status 2'];
// The latest status we want to filter
$T = 'status 2';
$result = MyModel::latestStatusEquals($T, $setS)->get();
背景:
目前,我正在获取所有用户的列表,然后在集合中进行过滤。
// Set of statuses to check for latest status:
$setS = ['status 1', 'status 2'];
// The latest status we want to filter
$T = 'status 2';
// The filtering using a collection:
$result = MyModel::get()->filter(function($model, $key){
return $model->latestStatus($setS)->name == $T;
});
问题与性能和可维护性有关。理想情况下,这将使用 Eloquent ORM(而不是过滤集合)来提高性能,并且使用范围更清晰。
编辑:
这是我在 SQL:
中的写法
select *
from users u
where u.id in (
select s.model_id
from statuses s
where s.id in (
-- Get the latest status from the set ('a', 'b', 'c')
select max(s2.id)
from statuses s2
where
s2.model_type = 'App\Models\User'
and s2.name in ('a', 'b', 'c')
group by s2.model_id
)
-- Return only rows where the latest status is 'b'
and s.name = 'b'
);
scopeCurrentStatus()
on hasStatus
将检索所有匹配 $setS
的用户状态,然后 bc 仍然在查询生成器上我认为这样做会做到:(未测试)
public function scopeLatestStatusEquals($query, $T, ...$setS)
{
$query->where(function(Builder $query) use ($setS) {
$query->currentStatus($setS)
})->where('name', $T);
]
这是我想出的:
public function scopeLatestStatusEquals(EloquentBuilder $builder, $names, $valid_names = null) {
$names = Arr::wrap($names);
// Return models with statuses of a certain criteria
$built = $builder
->whereHas('statuses', function ($query) use ($names, $valid_names) {
// Latest statuses that match the provided $names
$query
->whereIn('name', $names)
->whereIn('id', function($query) use ($valid_names) {
// Latest statuses
$query
->selectRaw('max(s2.id)')
->from('statuses as s2')
->where('s2.model_type', $this->getStatusModelType());
if ($valid_names) {
$query->whereIn('s2.name', $valid_names);
}
else {
// pass
}
// Grouping by model ID
$query->groupBy('s2.'.$this->getModelKeyColumnName());
}
);
});
return $built;
}
public function scopeLatestStatusMissing(EloquentBuilder $builder, $valid_names = null) {
// Return models with statuses of a certain criteria
$built = $builder
->whereDoesntHave('statuses', function ($query) use ($valid_names) {
// Missing latest statuses
$query
->whereIn('id', function($query) use ($valid_names) {
// Latest statuses
$query
->selectRaw('max(s2.id)')
->from('statuses as s2')
->where('s2.model_type', $this->getStatusModelType());
if ($valid_names) {
$query->whereIn('s2.name', $valid_names);
}
else {
// pass
}
// Grouping by model ID
$query->groupBy('s2.'.$this->getModelKeyColumnName());
}
);
});
return $built;
}
当前系统:
我正在使用 Laravel 和 Spatie 包 laravel-model-status
.
需要:
以下是我正在寻找的正式描述:
Get a list of users whose latest status in set S is the status T.
基本上,我正在寻找一个 Eloquent 可以变成本地范围的示例 scopeLatestStatusEquals($T, ...$setS)
。
这是它的用法:
// Set of statuses to check for latest status:
$setS = ['status 1', 'status 2'];
// The latest status we want to filter
$T = 'status 2';
$result = MyModel::latestStatusEquals($T, $setS)->get();
背景:
目前,我正在获取所有用户的列表,然后在集合中进行过滤。
// Set of statuses to check for latest status:
$setS = ['status 1', 'status 2'];
// The latest status we want to filter
$T = 'status 2';
// The filtering using a collection:
$result = MyModel::get()->filter(function($model, $key){
return $model->latestStatus($setS)->name == $T;
});
问题与性能和可维护性有关。理想情况下,这将使用 Eloquent ORM(而不是过滤集合)来提高性能,并且使用范围更清晰。
编辑:
这是我在 SQL:
select *
from users u
where u.id in (
select s.model_id
from statuses s
where s.id in (
-- Get the latest status from the set ('a', 'b', 'c')
select max(s2.id)
from statuses s2
where
s2.model_type = 'App\Models\User'
and s2.name in ('a', 'b', 'c')
group by s2.model_id
)
-- Return only rows where the latest status is 'b'
and s.name = 'b'
);
scopeCurrentStatus()
on hasStatus
将检索所有匹配 $setS
的用户状态,然后 bc 仍然在查询生成器上我认为这样做会做到:(未测试)
public function scopeLatestStatusEquals($query, $T, ...$setS)
{
$query->where(function(Builder $query) use ($setS) {
$query->currentStatus($setS)
})->where('name', $T);
]
这是我想出的:
public function scopeLatestStatusEquals(EloquentBuilder $builder, $names, $valid_names = null) {
$names = Arr::wrap($names);
// Return models with statuses of a certain criteria
$built = $builder
->whereHas('statuses', function ($query) use ($names, $valid_names) {
// Latest statuses that match the provided $names
$query
->whereIn('name', $names)
->whereIn('id', function($query) use ($valid_names) {
// Latest statuses
$query
->selectRaw('max(s2.id)')
->from('statuses as s2')
->where('s2.model_type', $this->getStatusModelType());
if ($valid_names) {
$query->whereIn('s2.name', $valid_names);
}
else {
// pass
}
// Grouping by model ID
$query->groupBy('s2.'.$this->getModelKeyColumnName());
}
);
});
return $built;
}
public function scopeLatestStatusMissing(EloquentBuilder $builder, $valid_names = null) {
// Return models with statuses of a certain criteria
$built = $builder
->whereDoesntHave('statuses', function ($query) use ($valid_names) {
// Missing latest statuses
$query
->whereIn('id', function($query) use ($valid_names) {
// Latest statuses
$query
->selectRaw('max(s2.id)')
->from('statuses as s2')
->where('s2.model_type', $this->getStatusModelType());
if ($valid_names) {
$query->whereIn('s2.name', $valid_names);
}
else {
// pass
}
// Grouping by model ID
$query->groupBy('s2.'.$this->getModelKeyColumnName());
}
);
});
return $built;
}