11

我有以下三个表:

A
-------------
| id | name |
-------------

B
--------------------
| id | A_id | name |
--------------------

C
--------------------
| id | B_id | name |
--------------------

因此,表C中的数据属于表中的数据,表中的数据B属于表中的数据A。现在,我想查询C,同时还从BandA中检索数据,下面的代码就可以了。

C::with('B.A')->get();

现在的问题是我想查询C一些约束。这些约束之一是idof A。我尝试了以下方法:

C::with(array('B.A' => function ($query)
{
    $query->where('id', '=', $constraint);
}))->get();

但似乎 Eloquent 会在C不考虑约束的情况下检索所有行,除非它执行查询以检索 table 中的数据A。我该如何解决这个问题?我是否需要在 中添加另一个字段C,即A_id,并与$constraint该字段匹配?

4

1 回答 1

20

您将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;

If you use it, on the other hand:

SELECT * FROM foos WHERE foos.something = 1;
SELECT * FROM bars WHERE bars.id IN (30, 57, 134, 1096); // Eager loading

When you add a condition to that with(), you are only constraining the eager loading of those dependencies, and not the first query.

Now to your answer

To achieve what you want, you'll need to use ->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.*');

I've included the with(), because I didn't know if you would need to access $c->b->a. If you don't, and you just need $c data, you can remove the with() since it will query for B's and A's unnecessarily.

于 2013-05-29T12:37:11.327 回答