Laravel雄辩:with()vs join()JSON输出
我对我的Laravel项目有以下两个疑问:Laravel雄辩:with()vs join()JSON输出,json,laravel,eloquent,Json,Laravel,Eloquent,我对我的Laravel项目有以下两个疑问: $questions = \App\Answer::rightJoin('questions','answers.id_question','=','questions.id_question') ->leftJoin('users','answers.id_user','=','users.id')->where([ ['questions.id_question', '=', $id_questi
$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);
及
基本上,第一个返回尚未回答的问题,第二个只返回已经回答的问题。
我试图对两者使用相同的blade视图,但它们有不同的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, ....."
}
以及:
如何使第一个查询返回与第二个查询相同的3个级别?
为什么会发生这种情况?第一个是更多地利用查询生成器,并将执行一个类似以下内容的查询:
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
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)
此查询将从所有表中返回数据,这些数据正是sql计算数据的方式。Laravel/Eloquent不知道如何将其可靠地转换为雄辩的格式
第二个将执行3个查询,如下所示:
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
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中,响应更难处理,因为php创建的代码可读性较差
我建议您使用内置的查询日志查看每个用户执行的查询
\DB::enableQueryLog();
$builtQuery->get()
dd(\DB::getQueryLog());
第一个是利用query builder more并执行一个查询,该查询如下所示:
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
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)
此查询将从所有表中返回数据,这些数据正是sql计算数据的方式。Laravel/Eloquent不知道如何将其可靠地转换为雄辩的格式
第二个将执行3个查询,如下所示:
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
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中,响应更难处理,因为php创建的代码可读性较差
我建议您使用内置的查询日志查看每个用户执行的查询
\DB::enableQueryLog();
$builtQuery->get()
dd(\DB::getQueryLog());
这是因为在你的第二个查询中,你利用你的雄辩的关系。Eloquent模型的默认
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。。。其中,(…)
中的id查询问题和用户模型,希望将其加载到各自的关系中。这是因为在第二次查询中,您利用它们来建立雄辩的关系。Eloquent模型的默认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。。。其中,(…)
查询问题
和用户
模型中的id将被急切加载到各自的关系中。使用急切加载更新了这两个查询,但使用了(['Question','User'])。现在,第一个从问题中检索用户,而第二个从答案(我想要的)中检索用户。为什么?@Paulo您的加入可能会打乱急切的加载,因为答案表和问题表都有id\u user
列(您通过它加入)。将->select('answers.*)
添加到您的第一个查询中(其中answers
是您的表的名称)。使用急切加载更新两个查询,但使用(['question','user'])。现在,第一个从问题中检索用户,而第二个从答案(我想要的)中检索用户。为什么?@Paulo您的加入可能会打乱急切的加载,因为答案表和问题表都有id\u user
列(您通过它加入)。将->select('answers.*)
添加到第一个查询中(其中answers
是表名)。