直到今天我依赖于Laravel的关系,但自从我打开mysql日志后我非常失望。
当我执行代码
时Company::with(['users', 'machines'])->get()
mysql.log
看起来就是这样
select * from `company` where `company`.`id` = '48' limit 1
select * from `user` where `user`.`company_id` in ('48')
select * from `machine` where `machine`.`company_id` in ('48')
为什么Laravel不使用连接进行急切提取?另外,有没有什么方法可以提高性能并仍然使用Laravel模型?
我知道通过使用连接,Doctrine ORM eager loading非常好用。
感谢您的帮助。
答案 0 :(得分:2)
如果你真的想使用连接而不是Eloquent计算查询,我想你可以使用流畅的查询构建器(通过数据库外观随Laravel一起提供)并将该代码粘贴到模型的方法中一切都很好和SRP。
例如:
function
这将为您生成正确的连接查询。
至于为什么要这样做,您必须对这两个选项进行基准测试,以确定哪个选项可以为您的特定数据提供最佳性能。我不会一概而论,一种选择总是比另一种更好/更差。
答案 1 :(得分:1)
正如评论中所述,我不确定性能方面为什么这是首选方法,但是从可用性来看,能够访问模型的关系,因为它拥有独立的属性比使用join
要容易得多,尤其是在many-to-one
关系的情况下。
让我们使用->with()
和->leftJoin()
方法比较上述示例。
使用->with()
时,每个关系都被定义为Company
的属性,可通过$company->users
访问。在此属性foreach()
上运行foreach($company->users AS $user)
循环并输出信息很容易,例如username
,email
等。另外,如果{{1}没有Company
,您不必担心显示空值(对于使用users
表示法链接模型尤其重要,例如.
)。
现在,看users.user_details
。如果您尝试在每个模型及其子模型上链接多个leftJoin()
,那么您很有可能无法获得您期望的结果。从本质上讲,leftJoins()
不会处理leftJoin()
个记录以及个别查询。
接下来,要输出公司用户的列表,您必须运行循环,例如:
NULL
由于foreach($company AS $row){
echo $row->username;
echo $row->email;
// etc etc
}
根本无法处理重复的属性,因此会出现问题。例如,如果公司有Eloquent
字段以及用户,那么任何人都可以猜测实际显示的是哪个字段。除非您执行email
,否则将只返回一个selectRaw("companies.email AS email, users.email AS user_email)"
属性。这也适用于像email
这样的列,其中多个将使用id
获取,但实际上只有一个可以访问。
长话短说,leftJoin()
在尝试连接多个表时可能存在大量问题,可能存在重复信息,空信息等。同时使用{{运行多个查询的性能1}}方法可能不是最好的,它允许更容易地用于检索和显示信息。