Laravel - 过滤 morphOne 或 hasOne 关系
Laravel - Filter morphOne or hasOne relationship
我有三个通过 morph
关系关联的模型。
Shipment
可以有多个 Status
个实例,通过一个 StatusHistory
class。
class Status extends Model {
//id, name
}
class Shipment extends Model {
public function latestStatus() {
return $this->morphOne('App\StatusHistory', 'model')->latest();
}
}
class StatusHistory extends Model {
public function model() {
return $this->morphTo();
}
public function status() {
return $this->belongsTo('App\Status', 'status_id');
}
}
我想获取所有 Shipment
个实体,其中 latestStatus
具有特定的 Status
名称值。
Shipment::whereHas('latestStatus', function($query) {
return $query->whereHas('status', function($query) {
return $query->where('name', 'reserved');
});
})->get();
这不起作用,return 状态为 'reserved' 的所有实体,即使 latestStatus
可以是其他状态。
有什么想法吗?
编辑(添加样本信息):
我有 2 批货物。
- 第一个只有一个状态名称中包含 'reserved' 的状态历史实例。
- 第二个有两个状态历史实例,其状态名称为 'reserved' 和 'shipped'。 'shipped' 的状态历史记录实例创建时间晚于 'reserver'。
所以:
- 第一批货物的最后状态为 'reserved'。
- 第二批货物的最后状态为 'shipped'。
电话应该只return第一批出货。
最简单的解决方案是获取所有货件并在之后过滤它们:
Shipment::with('latestStatus.status')->get()->where('latestStatus.status.name', 'reserved')
根据您的数据库大小,这可能不是很有效。
只获取相关货件的查询:
Shipment::select('shipments.*')
->join('status_histories as sh', 'shipments.id', 'sh.model_id')
->join('statuses as st', 'sh.status_id', 'st.id')
->where('model_type', Shipment::class)
->where('st.name', 'reserved')
->where('created_at', function($query) {
$query->selectRaw('MAX(created_at)')
->from('status_histories')
->where('model_id', DB::raw('sh.model_id'))
->where('model_type', DB::raw('sh.model_type'));
})->get();
我有三个通过 morph
关系关联的模型。
Shipment
可以有多个 Status
个实例,通过一个 StatusHistory
class。
class Status extends Model {
//id, name
}
class Shipment extends Model {
public function latestStatus() {
return $this->morphOne('App\StatusHistory', 'model')->latest();
}
}
class StatusHistory extends Model {
public function model() {
return $this->morphTo();
}
public function status() {
return $this->belongsTo('App\Status', 'status_id');
}
}
我想获取所有 Shipment
个实体,其中 latestStatus
具有特定的 Status
名称值。
Shipment::whereHas('latestStatus', function($query) {
return $query->whereHas('status', function($query) {
return $query->where('name', 'reserved');
});
})->get();
这不起作用,return 状态为 'reserved' 的所有实体,即使 latestStatus
可以是其他状态。
有什么想法吗?
编辑(添加样本信息):
我有 2 批货物。
- 第一个只有一个状态名称中包含 'reserved' 的状态历史实例。
- 第二个有两个状态历史实例,其状态名称为 'reserved' 和 'shipped'。 'shipped' 的状态历史记录实例创建时间晚于 'reserver'。
所以:
- 第一批货物的最后状态为 'reserved'。
- 第二批货物的最后状态为 'shipped'。
电话应该只return第一批出货。
最简单的解决方案是获取所有货件并在之后过滤它们:
Shipment::with('latestStatus.status')->get()->where('latestStatus.status.name', 'reserved')
根据您的数据库大小,这可能不是很有效。
只获取相关货件的查询:
Shipment::select('shipments.*')
->join('status_histories as sh', 'shipments.id', 'sh.model_id')
->join('statuses as st', 'sh.status_id', 'st.id')
->where('model_type', Shipment::class)
->where('st.name', 'reserved')
->where('created_at', function($query) {
$query->selectRaw('MAX(created_at)')
->from('status_histories')
->where('model_id', DB::raw('sh.model_id'))
->where('model_type', DB::raw('sh.model_type'));
})->get();