Laravel Collection
Collection
是laravel提供的对 array
进行包装的类。它有如下的特点:
- 函数式
- 流式API(Fluent API)
- 操作代理
- 可扩展
有一个数组 range(1,100)
,需要找出大于30的偶数。
过程式常规的实现方式:
$arr = range(1,100);
$result = [];
foreach (range(1,100) as $v){
if ($v > 30 && $v%2 == 0){ $result[] = $v; }}
Collection
流式和函数式的风格方式
$list = Collection::range(1,100);
$result = $list->filter(function ($v){
return $v > 30;})->filter(function ($v){
return $v % 2 ==0;});
通过将不同的过滤逻辑封装到不同的函数中,连续的对同一个列表调用 filter
方法,使得代码看起来情绪,写起来流畅。
操作代理的意思:需要对 Collection
执行某个操作,但具体操作细节在 Collection
元素对象上实现。
有一个名为 StudentScore
对象,该对象包含 chinese
和 math
两个分数的属性。现在需要分别计算列表中 chinses
和 math
的最高多。
非代理方式
class StudentScore
{
public $math;
public $chinese;
/** * StudentScore constructor. * @param $math * @param $chinese */
public function __construct($math, $chinese) { $this->math = $math; $this->chinese = $chinese; }}
$scores = collect([new StudentScore(mt_rand(60, 120), mt_rand(60, 120)),
new StudentScore(mt_rand(60, 120), mt_rand(60, 120)),
new StudentScore(mt_rand(60, 120), mt_rand(60, 120)),
]);
// 语文最高分
$chineseMaxScore = $scores->max(function (StudentScore $score){
return $score->chinese;
});
// 数学最高分
$mathMaxScore = $scores->max(function (StudentScore $score){
return $score->math;
});
// 全部学科最高分
$maxScore = $scores->max(function (StudentScore $score){
return max($score->chinese,$score->math);
});
如果最高分的逻辑计算需要在不同的地方多次使用,那么我们可以通过 Collection
的代理的方式,把具体的逻辑封装到类内部。
class StudentScore
{
public $math;
public $chinese;
/** * StudentScore constructor. * @param $math * @param $chinese */
public function __construct($math, $chinese) {
$this->math = $math;
$this->chinese = $chinese;
}
function chineseMaxScore(){
return $this->chinese;
}
function mathMaxScore(){
return $this->math;
}
function maxScore(){
return max($this->math,$this->chinese);
}
}
$scores = collect([new StudentScore(mt_rand(60, 120), mt_rand(60, 120)),
new StudentScore(mt_rand(60, 120), mt_rand(60, 120)), new StudentScore(mt_rand(60, 120), mt_rand(60, 120)), ]);
$maxProxy = $scores->max;
$chineseMaxScore = $maxProxy->chineseMaxScore();
$mathMaxScore = $maxProxy->mathMaxScore();
$maxScore = $maxProxy->maxScore();
dd($chineseMaxScore,$mathMaxScore,$maxScore);
使用proxy模式的优点是,可以把逻辑封装到类内部,多次使用。
某些场景下我们需要功能 Collection
并未提供,由于 Collection
使用了 Macroable
,可以使用 macr
接口扩展功能。
// 为 Collection 扩展 `pass` 方法
Collection::macro("pass",function ($cb){
return $this->filter($cb);});
$scores = Collection::range(1,10);
$passScores = $scores->pass(function ($v){
return $v > 5;});
dd($passScores);// output: [6,7,8,9,10]