Яркое вложенное отношение с некоторыми ограничениями

У меня следующие три таблицы:

A ------------- | id | name | ------------- B -------------------- | id | A_id | name | -------------------- C -------------------- | id | B_id | name | -------------------- 

Таким образом, данные в таблице C относятся к данным в таблице B которые относятся к данным в таблице A Теперь я хочу запросить C , а также получить данные из B и A и следующий код делает трюк просто прекрасным.

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

Проблема в том, что я хочу запросить C с некоторыми ограничениями. Одним из этих ограничений является id A Я пробовал следующее:

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

Но кажется, что Eloquent будет извлекать все строки в C даже не принимая во внимание ограничение, за исключением случаев, когда он выполняет запрос для извлечения данных в таблице A Как мне обойти эту проблему? Нужно ли мне добавить другое поле в C , то есть A_id , и сопоставить $constraint с этим полем?

Solutions Collecting From Web of "Яркое вложенное отношение с некоторыми ограничениями"

Вы смешиваете метод with() с JOIN SQL, и это происходит очень часто.

Сначала немного фона

Когда вы используете 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 без необходимости.