我在Laravel项目中有以下两个查询:
$questions = \App\Answer::rightJoin('questions','answers.id_question','=','questions.id_question')
->leftJoin('users','answers.id_user','=','users.id')->where([
['questions.id_question', '=', $id_question],
['questions.flg_active', '=', true],
])->orderBy('questions.created_at', 'desc')->paginate(5);
和
$questions = \App\Answer::with('question.user')
->orderBy('created_at', 'desc')->paginate(15);
从本质上讲,第一个返回未回答的问题,第二个仅返回已经回答的问题。 我试图为两者使用相同的刀片视图,但是它们具有不同的JSON输出结构。
第一个返回一个级别的JSON,而第二个返回3个级别的数据。
"data": [{
"id_answer": 42,
"created_at": "2018-11-28 17:52:18",
"updated_at": "2019-05-24 15:09:14",
"id_user": 2,
"id_question": 42,
"str_answer": "onono onooono nonono onn ",
"str_question": "ononon ononon onononn ?",
"url_link": null,
"flg_active": 1,
"id": 1,
"name": "Paul",
"surname": null,
"email": "p@yahoo.com",
"certification": "CFA ...",
"about": "CS, ....."
}
和:
"data": [{
"id_answer": 64,
"created_at": "2019-05-16 15:46:54",
"updated_at": "2019-05-16 15:46:54",
"id_user": 2,
"id_question": 98,
"str_answer": "onono non ooonononn",
"question": {
"id_question": 98,
"created_at": "2019-05-16 15:06:31",
"updated_at": "2019-05-16 15:24:43",
"id_user": 2,
"str_question": "onono onnon ononon?",
"url_link": null,
"flg_active": 1,
"user": {
"id": 2,
"name": "Paul",
"surname": null,
"email": "p@outlook.com",
"created_at": "2018-12-06 05:50:09",
"updated_at": "2019-05-24 11:23:32",
"certification": null,
"about": null
}
}
}
如何使第一个查询返回与第二个查询相同的3个级别?
为什么会这样?
答案 0 :(得分:1)
第一个是更多地利用查询生成器,并将执行一个如下所示的查询:
SELECT * FROM answer
RIGHT JOIN questions ON answers.id_question = questions.id_question
LEFT JOIN users ON answers.id_user = users.id
WHERE questions.id_question = $id_question
AND questions.flg_active = true
ORDER BY questions.created_at desc
OFFSET 0
LIMIT 15
此查询从所有表返回的数据与sql的计算方式完全相同。 Laravel / Eloquent不知道如何可靠地将其转换为雄辩的格式。
第二个查询将执行3个查询,如下所示:
SELECT * FROM answer
ORDER BY created_at desc
OFFSET 0
LIMIT 15
SELECT * FROM question
WHERE answer_Id IN ($answer_ids) // Will be like (1, 5, 6, 7). All the ids retrieve from the first query
SELECT * FROM user
WHERE queston_id IN ($user_ids)
Eloquent进行3次查询,因此可以可靠地创建您概述的结构。
最终这是一个折衷方案,第一个选项更快,但是响应更难在php中使用,这会导致可读性降低。
我建议您使用内置的查询日志查看每个查询所执行的查询。
\DB::enableQueryLog();
$builtQuery->get()
dd(\DB::getQueryLog());
答案 1 :(得分:1)
之所以会这样,是因为在第二个查询中,您将eager loading用于雄辩的关系。雄辩的模型的默认<script src="https://unpkg.com/vue"></script>
<div id="app">
<expandable>
<p>no model</p>
</expandable>
<expandable v-model="isOpen">
<p>has model</p>
</expandable>
</div>
方法将其属性和已加载的关系合并到一个表示中。
另一方面,您的第一个查询将联接表,但不会加载任何关系。因此,最简单的方法是像在第二个查询中一样,渴望在第一个查询中加载这些关系:
toArray()
请注意,这将对 $questions = \App\Answer::with('questions.user')
->rightJoin('questions','answers.id_question','=','questions.id_question')
->leftJoin('users','answers.id_user','=','users.id')->where([
['questions.id_question', '=', $id_question],
['questions.flg_active', '=', true],
])->orderBy('questions.created_at', 'desc')->paginate(5);
和SELECT ... WHERE id IN (...)
模型产生额外的Question
查询,以急于加载到它们各自的关系中。