我有以下三个表:
A
-------------
| id | name |
-------------
B
--------------------
| id | A_id | name |
--------------------
C
--------------------
| id | B_id | name |
--------------------
因此,表C
中的数据属于表B
中的数据,表B
中的数据属于表A
中的数据。现在,我想查询 C
,同时还从 B
和 A
检索数据,下面的代码就可以很好地实现这一目的。
C::with('B.A')->get();
现在的问题是,我想在某些约束条件下查询 C
。其中一个约束是 A
的 id
。我尝试了以下方法:
C::with(array('B.A' => function ($query)
{
$query->where('id', '=', $constraint);
}))->get();
但似乎 Eloquent 将检索 C
中的所有行,甚至不考虑约束,除非它正在执行查询以检索表 A
中的数据。我该如何解决这个问题?我是否需要在 C
中添加另一个字段,即 A_id
,并将 $constraint
与该字段匹配?
最佳答案
您将 with()
方法与 SQL 的 JOIN
混淆了,这种情况经常发生。
先介绍一下背景
当你使用 Foo::with('bar')->where_something(1)
时,Laravel 将首先加载 Foo
然后根据 Foo.bar_id
,它将加载 Bar
。它的目的是告诉 Laravel 急切加载模型对组合查询的依赖性,从而大大提高这些模型的迭代性能。
如果你不使用它,应该执行以下查询:
SELECT * FROM foos WHERE foos.something = 1;
SELECT * FROM bars WHERE bars.id = 30;
SELECT * FROM bars WHERE bars.id = 57;
SELECT * FROM bars WHERE bars.id = 134;
SELECT * FROM bars WHERE bars.id = 1096;
如果你使用它,另一方面:
SELECT * FROM foos WHERE foos.something = 1;
SELECT * FROM bars WHERE bars.id IN (30, 57, 134, 1096); // Eager loading
当您向 with()
添加条件时,您只是限制了这些依赖项的预加载,而不是第一个查询。
现在回答你的问题
要实现您想要的效果,您需要使用 ->join()
。
C::with(array('b', 'b.a'))
->join('b', 'b.id', '=', 'c.b_id')
->join('a', 'a.id', '=', 'b.a_id')
->where('a.id', '=', $ID)
->get('c.*');
我包含了 with()
,因为我不知道您是否需要访问 $c->b->a
。如果您不这样做,并且您只需要 $c
数据,则可以删除 with()
,因为它会不必要地查询 B 和 A。
关于php - Eloquent 嵌套关系与一些约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16789285/