【问题标题】:Convert Laravel query to Eager Loading将 Laravel 查询转换为 Eager Loading
【发布时间】:2014-12-13 13:20:31
【问题描述】:

我一直在学习 Laravel 并尝试实现一些东西,我做到了,它奏效了,但我听说使用 Eager Loading 可以以更简单的方式做同样的事情。

假设我们有 4 个表:garagescarssecuritiesplaces

garages 是您可以找到 cars 的地方,securities 是确保汽车在车库内安全的安全措施,places 是您可以找到与该车库类似的车库的地方。

我想要列出garages 并像这样加入carssecuritiesplaces 这三个表:

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();

正如我上面所说,它正在工作,但我想知道是否有更简单的方法来使用 Eager Loading 以及如何转换?

  • 当我说更简单时,我的意思是更易读、更独立、更正确,而不是那种大查询。

【问题讨论】:

    标签: php laravel eager-loading


    【解决方案1】:

    假设您确实有 4 个用于实体的 Eloquent Model 类。 如果是这种情况,您可以尝试通过 Eloquent ORM 进行预加载。

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

    然后您可以使用返回的结果集(Illuminate\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

    【讨论】:

    • 它返回carsplaces 的总和,但securities 始终为0。
    • 我自己使用hasManyThrough解决了这个问题。 - 但是现在当我将数组传递给刀片模板时出现错误:Trying to get property of non-object。如何解决?
    • 尝试通过对象集合进行调试以查看是否加载了关系,错误告诉您无论您尝试获取的对象->属性在该对象上不可用。
    猜你喜欢
    • 1970-01-01
    • 2021-10-17
    • 1970-01-01
    • 2017-08-19
    • 1970-01-01
    • 2018-06-15
    • 2019-06-23
    • 1970-01-01
    • 2020-05-23
    相关资源
    最近更新 更多