传统的 mvc框架 下,都需要从 controller 层分配数据,在 view 层中渲染。在列表视图页中,我们时常会遇到如下的场景:

分案时间分案对象分案金额分案笔数
2019-10-10 13:02:20委外机构1772.2010
2019-10-10 10:12:32
委外机构21092.2221
............

注意上面的“分案对象”这一栏,这一栏在视图中读取的数据是对象id,在页面中需要渲染对象名称,这种情况下,就需要我们封装一个函数 getObjName(),将对象id转化为对象名称。

Laravel5框架中,我一般会自己封装一个常用的函数,比如 /bootstrap/helper.php,用来封装一些常用的自定义函数。

如果我们按照正常思路来封装这个转化函数,大概实现方式是这样的:

function getObjName($id){
    $obj = \App\Models\ObjModel::find(id);
    return $obj->name;
}

这种方式虽然能实现将对象id转化为对象名称的需求,但是效率特别低。主要问题在于,加入页面有20条数据,就要调用20次 getObjName($id) ,进而要进行20次find查询。

想要优化这个问题,关键在于减少数据库查询次数,优化的方法有多种,比如说将查询内容做缓存,就是一种处理方案,实现方案也比较简单,在这里我就不过多赘述了。

除了缓存方法,我还想给大家介绍另一种比较巧妙的方法:使用静态变量,缓存单次请求的重复调用问题。

function getObjName($id){
    static $objArr = [];
    if(!isset($objArr[$id])){
        $obj = \App\Models\ObjModel::find(id);
        $objArr[$id] = $obj->name;    
    }
    return $objArr[$id];
}

这样,就可以避免同一个id,多次重复查询的情况。

当然如果列表中id的分布广、重复少,这种优化方案效果不大,依然会有很多次查库操作,这种情况下,我们可以对以上方案做一个简单的修改:

function getObjName($id){
    static $objArr = [];
    if(!$objArr){
        $objArr = \App\Models\ObjModel::pluck('name','id')->toArray();
    }
    return isset($objArr[$id])?$objArr[$id]:'--';
}

这样我们只需要将obj表中的数据,一次全部查询出来做缓存,一次请求的多次调用就不会重发查表了。当然这种方案也只适合obj表中数据量较少的情况。

具体情况应该如何处理,大家合理评估,这里只是给大家提供另一种思路,做抛砖引玉。

本文为 陈华 原创,欢迎转载,但请注明出处:http://edu.ichenhua.cn/read/16