問題描述
我有以下三個表:
A
-------------
| id | name |
-------------
B
--------------------
| id | A_id | name |
--------------------
C
--------------------
| id | B_id | name |
--------------------
所以,C
表的數(shù)據(jù)屬于B
表的數(shù)據(jù),A
表的數(shù)據(jù).現(xiàn)在,我想查詢 C
,同時還從 B
和 A
檢索數(shù)據(jù),下面的代碼可以很好地解決問題.
So, the data in table C
belongs to the data in table B
which belongs to the data in table A
. Now, I want to query C
, while also retrieving data from B
and A
and the following code does the trick just fine.
C::with('B.A')->get();
現(xiàn)在的問題是,我想用一些約束來查詢 C
.這些約束之一是A
的id
.我嘗試了以下方法:
The problem now, is that I want to query C
with some constraints. One of these constraints is the id
of A
. I've tried the following:
C::with(array('B.A' => function ($query)
{
$query->where('id', '=', $constraint);
}))->get();
但似乎 Eloquent 會檢索 C
中的所有行,甚至不考慮約束,除非它執(zhí)行查詢以檢索表 A
中的數(shù)據(jù).我該如何解決這個問題?我是否需要在 C
中添加另一個字段,即 A_id
,并將 $constraint
與該字段匹配?
But it seems that Eloquent will retrieve all the rows in C
without even taking the constraint into account, except when it's executing the query to retrieve data in table A
. How do I get around this problem? Do I need to add another field in C
, that is A_id
, and match $constraint
against that field?
推薦答案
您將 with()
方法與 SQL 的 JOIN
混淆,這種情況經(jīng)常發(fā)生.
You are confusing the with()
method with SQL's JOIN
and that happens a lot.
>
首先介紹一下背景
當(dāng)你使用 Foo::with('bar')->where_something(1)
時,Laravel 將首先加載 Foo
然后,基于 Foo.bar_id
,它將加載Bar
.它的目的是告訴 Laravel 在組合查詢上預(yù)先加載模型的依賴項,從而大大提高這些模型的迭代性能.
When you use Foo::with('bar')->where_something(1)
, Laravel will first load the Foo
and then, based on Foo.bar_id
, it will load the Bar
. It serves the purpose of telling Laravel to eager load dependencies of your model on a combined query, greatly improving performance of iterations on those models.
如果你不使用它,應(yīng)該執(zhí)行以下查詢:
If you don't use it, the following queries should be executed:
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
當(dāng)您向 with()
添加條件時,您只會限制這些依賴項的預(yù)加載,而不是第一個查詢.
When you add a condition to that with()
, you are only constraining the eager loading of those dependencies, and not the first query.
要實現(xiàn)您想要的,您需要使用 ->join()
.
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.*');
我已經(jīng)包含了 with()
,因為我不知道您是否需要訪問 $c->b->a
.如果你不這樣做,而你只需要 $c
數(shù)據(jù),你可以刪除 with()
因為它會不必要地查詢 B 和 A.
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.
這篇關(guān)于帶有一些約束的 Eloquent 嵌套關(guān)系的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!