2014-12-13 4 views
0

Я склоняюсь к Laravel и пытаюсь что-то реализовать, и я это сделал, это сработало, но я слышал, что можно сделать то же самое проще, используя Eager Loading.Convert Laravel query to Eager Loading

Представьте, что у нас есть 4 стола: garages, cars, securities, places.

garages, где вы можете найти cars, securities является безопасность, которая держит эту машину безопасно внутри гаража, и places, где вы можете найти гаражи, подобные тем.

То, что я хочу, чтобы перечислить garages и присоединиться три таблицы, является cars, securities и places так:

Garage 1 has 2 cars with 3 securities and has 3 more garages similar 
Garage 2 has 1 cars with 1 securities and has 2 more garages similar 

А вот запрос:

select 
    g.garage_name, 
    count(distinct c.car_id) as count_cars, 
    count(distinct s.security_id) as count_securities, 
    count(distinct p.place_id) as count_places 
from garages g 
left join cars c on c.garage_id = g.garage_id 
left join securities s on s.car_id = c.car_id 
left join places p on p.garage_id = g.garage_id 
group by g.garage_name 
order by g.garage_name; 

Это работает, как и вы можете увидеть here.

я преобразовал его:

$garages = Garages::select('garage_name', 
DB::raw('count(distinct cars.car_id) as count_cars'), 
DB::raw('count(distinct securities.security_id) as count_securities'), 
DB::raw('count(distinct places.place_id) as count_places')) 
->leftJoin('cars', 'cars.garage_id', '=', 'garages.garage_id') 
->leftJoin('securities', 'securities.car_id', '=', 'cars.car_id') 
->leftJoin('places', 'places.garage_id', '=', 'garages.garage.id') 
->groupBy('garages.garage_name') 
->orderBy('garages.garage_name') 
->get(); 

Как я уже говорил выше, это работает, но мне интересно, если есть более простой способ сделать это с помощью жадной загрузки и как конвертировать?

  • Когда я говорю проще, я имею в виду более читаемый, разделенный, правильный путь вместо этого большого запроса.

ответ

3

Допустим, у вас есть классы 4 класса Eloquent Model для объектов. Если это так, вы можете попробовать энергично загрузиться через Eloquent ORM.

$Garages = Garage::with(['cars','places', 'securities'])->get(); 

Тогда вы можете подготовить необходимый вывод, как вам нравится с помощью возвращаемого результирующего набора, который представляет собой набор (Осветите \ Support \ Collection). Вы можете преобразовать элементы в коллекции так, как вам нравится. Вот пример.

В вашем случае я предполагаю, что это будет способ сделать это.

$Garages->transform(function($garage) { 
    return array(
     'garage_name' => $garage->garage_name, 
     'count_cars' => $garage->cars->count(), 
     'count_securities' => $garage->securities->count(), 
     'count_places' => $garage->places->count(), 
     // add as many custom details you want here 
    ); 
}); 

return $Garages->toArray(); // see the output 

Теперь я надеюсь, что у вас есть идея.

Имейте в виду, что ваши файлы классов моделей должны иметь отношения. Это должно выглядеть следующим образом.

class Garage extends Eloquent { 

    public function cars() { 
    return $this->hasMany('Car'); 
    } 

    public function securities() 
    { 
    return $this->hasMany('Security'); 
    } 

    public function places() 
    { 
    return $this->hasMany('Place'); 
    } 

} 

class Car extends Eloquent { 

    // relationships here 
} 

class Security extends Eloquent { 

    // relationships here 
} 

class Place extends Eloquent { 

    // relationships here 
} 

Это простой пример, который поможет вам понять.

Наслаждайтесь! : D

+0

Он возвращает общее количество «автомобилей» и «мест», но «ценные бумаги» все еще всегда в 0. – yayuj

+0

Я сам решил это, используя 'hasManyThrough'. - Но теперь я получил сообщение об ошибке, когда передаю массив шаблону клика: 'Попытка получить свойство не-объекта'. Как это решить? – yayuj

+0

Попробуйте выполнить отладку через коллекцию объектов, чтобы узнать, загружены ли отношения, ошибка сообщает вам, что независимо от того, что свойство object->, которое вы пытаетесь получить, недоступно для объекта. – Raftalks