我想在 Laravel 中
Pivot
表中 Person
和 Topics
之间应用 where 条件。
我基本上有一张
Person
桌子和一张Topics
桌子。
中间有一个数据透视表
person_topic
,其中包含两个外键(person_id
和 topic_id
)以及 quantity
。
我放置了一个带有
::query()
的 whereHas
方法,该方法基于“主题 id”数组,在数据透视表中执行 whereIn
条件 person_topics
。
$from = request('from');
$to = request('to');
$topics = request('topics');
$unity = request('unity');
$limit = request('limit');
$eventsQuery = Event::query();
if (! is_null($topics) && $topics != "undefined") {
$topics = array_map('intval', explode(',', $topics));
$eventsQuery = $eventsQuery->whereHas('person.topics', function ($query) use ($topics) {
return $query->whereIn('topic_id', $topics);
});
}
$events = $eventsQuery->orderBy('date', 'DESC')
->whereIn('station_id', [$unity])
->whereBetween('date', [$from, $to])
->with('person')
->with('person.country')
->with('train')
->with('station')
->limit($limit)
->get();
return response()->json([
'events' => $events,
'message' => 'Success'
], 200);
该方法有效并返回了预期的结果,只是需要 2 分钟才能收到响应。
如何优化/修改我的代码以使我的请求执行得更好?
完整方法代码
$from = request('from');
$to = request('to');
$topics = request('topics');
$trains = request('trains');
$countries = request('countries');
$unity = request('unity');
$limit = request('limit');
if(is_null($trains) && $trains == "undefined" ){
$limit = Event::count();
}
$eventsQuery = Event::query();
if(!is_null($countries) && $countries != "undefined" ){
$countries = array_map('intval', explode(',', $countries));
$eventsQuery = $eventsQuery->whereHas('person.country', function ($query) use ($countries) {
return $query->whereIn('id', $countries);
});
}
if(!is_null($trains) && $trains != "undefined" ){
$trains = array_map('intval', explode(',', $trains));
$eventsQuery = $eventsQuery->whereHas('train', function ($query) use ($trains) {
return $query->whereIn('id', $trains);
});
}
if(!is_null($topics) && $topics != "undefined" ){
$topics = array_map('intval', explode(',', $topics));
$eventsQuery = $eventsQuery->whereHas('person.topics', function ($query) use ($topics) {
return $query->whereIn('topic_id', $topics);
});
}
$events = $eventsQuery->orderBy('date','DESC')->whereIn('station_id', [$unity])->whereBetween('date',[$from, $to])->with('person')->with('person.country')->with('train')->with('station')->limit($limit)->get();
return response()->json([
'events' => $events,
'countries' => $countries,
'message' => 'Success'
], 200);
你可以试试这个:
确保您创建了 2 个模型:
Person
和 Topic
PersonTopic
模型并定义 2 个这样的关系
public function person()
{
return $this->belongsTo('App\Models\Person', 'person_id', 'id');
}
public function topic()
{
return $this->belongsTo('App\Models\Topic', 'topic_id', 'id');
}
然后就可以查询了
if(!is_null($topics) && $topics != "undefined" ){
$topicIds = array_map('intval', explode(',', $topics));
$rows = PersonTopic::with(['person', 'topic'])
->whereIn('topic_id', $topicIds)
//can use whereHas if you want
->whereHas('topic', function ($query) use ($request) {
$query->where('topics.column', $request->column);
})
->get();
}
使用
foreach
循环获取详细信息
foreach ($rows as $row) {
//get person detail
$person = $row->person;
//get topic detail
$topic = $row->topic;
}
如果您将人员的外键放入事件表中,则可以使用连接到人员和主题表的数据透视表而不是 where has 来优化查询。
查询:
$eventsQuery = $eventsQuery->whereHas('person.topics', function ($query) use ($topics) {
return $query->whereIn('topic_id', $topics);
});
可以替换为:
$eventsQuery->join(
'person_topic',
'person_topic.person_id',
'=',
'events.person_id'
)
->whereIn('person_topic.topic_id', $topics);