Laravel Collection

Laravel框架
466
0
0
2022-04-18
标签   Laravel基础

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 对象,该对象包含 chinesemath 两个分数的属性。现在需要分别计算列表中 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]