Laravel 调试工具 Laravel-debugbar 试用

原文:http://blog.tanteng.me/2016/08/laravel-deb...

给 Laravel 项目安装了 debugbar 调试工具,在 debug 模式下打开页面底部会出现一个工具条,点开可以查看各项性能统计,最重要的是打印页面执行的 sql 语句和调试内容。下面利用 debugbar 工具找到一个 sql 查询的优化点。

优化页面 sql 查询

这里有两个模型,目的地模型和游记模型,他们是一对多的关系,在目的地模型 Destination.php 的 Model 中关系定义如下:

/**
 * 定义目的地-游记的一对多关系
 * @return \Illuminate\Database\Eloquent\Relations\HasMany
 */
public function travel()
{
    return $this->hasMany(Travel::class, 'destination_id');
}

为了统计每个目的地下有多少篇游记,用到了 Laravel 模型很好用的一个特性 appends,定义 appends 数组就是自定义了表字段:

/**
 * 自定义字段
 * @var array
 */
protected $appends = [
    'url',
    'first_travel_url',
    'total',
];

这里 total 指的就是目的地下一共有多少篇游记,优化前的代码是这样的:

/**
 * 目的地游记数
 * @return mixed
 */
public function getTotalAttribute()
{
    return $this->travel()->count();
}

这样就导致遍历目的地查询游记的总数,增加 sql 语句频次。这本来是个很好的特性,但是如果要额外查询数据库可能会增加查询开销。debugbar 工具在页面上打印了该页面执行的所有 sql 语句,如图:

debugbar

显然这里需要进行优化,需要用group by目的地的方式统计,只需要一条sql语句就可以了。

Laravel 中使用 group by 进行统计

在游记模型 Travel.php 的 Model 中增加一个方法:

/**
 * 获取每个目的地的游记总数
 * @return array
 */
public function getTravelNumsGroupByDestination()
{
    $travelNums = [];
    $result = $this->groupBy('destination_id')->get(['destination_id', DB::raw('count(*) as total')]);
    foreach ($result as $item) {
        $travelNums[$item->destination_id] = $item->total;
    }
    return $travelNums;
}

这里 $result 返回的是一个 Collection 对象,里面是 Travel 类的集合,实际上执行的 sql 语句是:select destination_id, count(*) as total from travel group by destination_id

by

在页面控制器 TravelController.php 的 index 方法中调用这个方法,然后赋值给模板即可。

/**
 * 游记首页
 * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
 */
public function index()
{
    $data = Cache::remember('travel.index', self::CACHE_TIME, function () {
        $destinationList = $this->destination->getList(12);
        $travelList = $this->travel->latest('begin_date')->take(12)->get();
        $travelNums = $this->travel->getTravelNumsGroupByDestination();
        return [
            'destinationList' => $destinationList,
            'travelList' => $travelList,
            'travelNums' => $travelNums
        ];
    });
    return view('travel.index', $data);
}

在模板中做出相应的修改,就完成了这个 sql 的性能优化,如果查询多的话这可以减少大量的 sql 查询。

优化后页面执行 sql 的情况:

optimizi

通过 debugbar 工具可以很好的掌握各项性能,不仅如此,他是个很好的调试工具,我们可以通过打印 log 的方式调试代码,也可以用 debugbar 提供的调试方法打印内容,很方便,使用 Laravel 开发必备的调试工具。

有用的链接

本帖已被设为精华帖!
本帖由 Summer 于 7年前 加精
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 5

这里查询的结果用 Redis 做了缓存,这是缓存失效第一次查数据的页面 sql 优化

7年前 评论

纯粹api接口调试,怎么使用这个工具

4年前 评论

@WilliamQian 可以使 Postman 测试

4年前 评论
kevin2011 4年前
kevin2011 4年前
董雷 4年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!