Laravel 5.1:lists()集合排序、代码优化及修改器调用问题
Laravel 5.1 三个问题的解决方案
嘿,针对你提出的三个Laravel 5.1技术问题,结合你的代码示例,我给你梳理下解决方案:
问题1:如何使用lists()方法对集合进行排序?
排序主要有两种思路,看你更看重性能还是便捷性:
- 数据库层面排序(推荐):直接在查询阶段就让数据库完成排序,性能更优,适合数据量大的场景。因为你的
name是通过修改器拼接的,需要用DB::raw模拟修改器的逻辑来排序:
public function listAgents($emptyLabel = '--Select Agent--'){ $sortedList = $this->orderBy(DB::raw('CONCAT(lname, ", ", fname, " ", mname)')) ->lists('name', 'id'); return withEmpty($sortedList, $emptyLabel); }
- 集合层面排序:如果已经拿到了模型集合,可以用集合的
sortBy()方法,它会自动触发你的name访问器(修改器)来完成排序:
public function listAgents($emptyLabel = '--Select Agent--'){ $sortedList = $this->all() ->sortBy('name') ->lists('name', 'id') ->all(); return withEmpty($sortedList, $emptyLabel); }
注意这种方式是把所有数据加载到内存后再排序,数据多的时候要谨慎使用。
问题2:简化$this->all()->lists('name', 'id')->all()的冗余
这段代码其实做了多余的操作:$this->all()返回模型集合,集合的lists()又返回一个集合,最后all()再把集合转成数组。其实你可以直接调用模型的lists()方法,它底层基于查询构建器直接返回数组,完全不需要中间的集合转换步骤。
简化后的代码:
public function listAgents($emptyLabel = '--Select Agent--'){ return withEmpty($this->lists('name', 'id'), $emptyLabel); }
这样既简洁又高效,省去了两次集合相关的操作。
问题3:如何使用orderBy方法调用修改器(mutator)?
这里要先明确一个关键点:修改器是在模型实例化后,获取属性时才会触发的,而orderBy()是数据库层面执行的SQL语句,数据库根本不知道你定义的name访问器,所以直接写orderBy('name')是无效的。
给你两种可行的解决方案:
- 数据库层面模拟修改器逻辑:用
DB::raw在orderBy里拼接字段,和你的getNameAttribute逻辑保持一致,让数据库按拼接后的字符串排序:
$this->orderBy(DB::raw('CONCAT(lname, ", ", fname, " ", mname)'))->lists('name', 'id');
这种方式性能最佳,因为排序在数据库端完成,适合大数据量场景。
2. 集合层面排序:先获取所有模型集合,再用集合的sortBy()方法,它会自动调用你的name访问器来排序:
$this->all()->sortBy('name')->lists('name', 'id')->all();
这种方式代码更简洁,但只适合数据量不大的场景,因为所有数据都要加载到内存中处理。
内容的提问来源于stack exchange,提问作者jp.palubs
相关产品推荐
相关产品推荐

