這篇筆記用來整理Collection 在Laravel 的實際應用場景。
求和
需求:遍歷$orders 陣列,求price 的和。
<?php // 引入package require __DIR__ . '/vendor/autoload.php'; $orders = [[ 'id' => 1, 'user_id' => 1, 'number' => '13908080808', 'status' => 0, 'fee' => 10, 'discount' => 44, 'order_products'=> [ ['order_id'=>1,'product_id'=>1,'param'=>'6寸','price'=>555.00,'product'=>['id'=>1,'name'=>'蛋糕名稱','images'=>[]]], ['order_id'=>1,'product_id'=>1,'param'=>'7寸','price'=>333.00,'product'=>['id'=>1,'name'=>'蛋糕名稱','images'=>[]]], ], ]];1.使用傳統的foreach 方式進行遍歷:
$sum = 0; foreach ($orders as $order) { foreach ($order['order_products'] as $item) { $sum += $item['price']; } } echo $sum;2.使用集合的map、flatten、sum:
$sum = collect($orders)->map(function($order){ return $order['order_products']; })->flatten(1)->map(function($order){ return $order['price']; })->sum(); echo $sum;
map:遍歷集合,返回一個新的集合。
flatten:將多維陣列轉換為一維。
sum:返回陣列的和。
$sum = collect($orders)->flatMap(function($order){ return $order['order_products']; })->pluck('price')->sum(); echo $sum;
flatMap:和map
類似,不過區別在於flatMap
可以直接使用返回的新集合。
$sum = collect($orders)->flatMap(function($order){ return $order['order_products']; })->sum('price');
sum:可以接收一個列名作為引數進行求和。
格式化資料
需求:將如下結構的陣列,格式化成下面的新陣列。
// 帶格式化陣列 $gates = [ 'BaiYun_A_A17', 'BeiJing_J7', 'ShuangLiu_K203', 'HongQiao_A157', 'A2', 'BaiYun_B_B230' ]; // 新陣列 $boards = [ 'A17', 'J7', 'K203', 'A157', 'A2', 'B230' ];1.使用foreach 進行遍歷:
$res = []; foreach($gates as $key => $gate) { if(strpos($gate, '_') === false) { $res[$key] = $gate; }else{ $offset = strrpos($gate, '_') + 1; $res[$key] = mb_substr($gate , $offset); } } var_dump($res);2.使用集合的map以及php 的explode、end:
$res = collect($gates)->map(function($gate) { $parts = explode('_', $gate); return end($parts); });3.使用集合的map、explode、last、toArray:
$res = collect($gates)->map(function($gate) { return collect(explode('_', $gate))->last(); })->toArray();
explode:將字串進行分割成陣列
last:獲取最後一個元素
統計GitHub Event
首先,透過此連結獲取到個人事件json。
一個 PushEvent計
5 分,一個 CreateEvent
計 4 分,一個 IssueCommentEvent計
3 分,一個 IssueCommentEvent
計 2 分,除此之外的其它型別的事件計 1 分,計算當前使用者的時間得分總和。
$opts = [ 'http' => [ 'method' => 'GET', 'header' => [ 'User-Agent: PHP' ] ] ]; $context = stream_context_create($opts); $events = json_decode(file_get_contents('', false, $context), true);1.傳統foreach 方式:
$eventTypes = []; // 事件型別 $score = 0; // 總得分 foreach ($events as $event) { $eventTypes[] = $event['type']; } foreach($eventTypes as $eventType) { switch ($eventType) { case 'PushEvent': $score += 5; break; case 'CreateEvent': $score += 4; break; case 'IssueEvent': $score += 3; break; case 'IssueCommentEvent': $score += 2; break; default: $score += 1; break; } }2.使用集合的map、pluck、sum 方法:
$score = $events->pluck('type')->map(function($eventType) { switch ($eventType) { case 'PushEvent': return 5; case 'CreateEvent': return 4; case 'IssueEvent': return 3; case 'IssueCommentEvent': return 2; default: return 1; } })->sum();
使用集合的鏈式程式設計,可以很好地解決上面那種多次遍歷的問題。
3.使用集合中的map、pluck、get 方法:$score = $events->pluck('type')->map(function($eventType) { return collect([ 'PushEvent'=> 5, 'CreateEvent'=> 4, 'IssueEvent'=> 3, 'IssueCommentEvent'=> 2 ])->get($eventType, 1); // 如果不存在則預設等於1 })->sum();4.嘗試將該需求,封裝成一個類:
class GithubScore { private $events; private function __construct($events){ $this->events = $events; } public static function score($events) { return (new static($events))->scoreEvents(); } private function scoreEvents() { return $this->events->pluck('type')->map(function($eventType){ return $this->lookupEventScore($eventType, 1); })->sum(); } public function lookupEventScore($eventType, $default_value) { return collect([ 'PushEvent'=> 5, 'CreateEvent'=> 4, 'IssueEvent'=> 3, 'IssueCommentEvent'=> 2 ])->get($eventType, $default_value); // 如果不存在則預設等於1 } } var_dump(GithubScore::score($events));
格式化資料
需求:將以下資料格式化成新的結構。
$messages = [ 'Should be working now for all Providers.', 'If you see one where spaces are in the title let me know.', 'But there should not have blank in the key of config or .env file.' ]; // 格式化之後的結果 - Should be working now for all Providers. n - If you see one where spaces are in the title let me know. n - But there should not have blank in the key of config or .env file.1.傳統的foreach 方式:
$comment = '- ' . array_shift($messages); foreach ($messages as $message) { $comment .= "n - ${message}"; } var_dump($comment);2.使用集合的map、implode方法:
$comment = collect($messages)->map(function($message){ return '- ' . $message; })->implode("n"); var_dump($comment);
多個陣列求差
需求:兩組資料分別代表去年的營收和今年的營收,求每個月的盈虧情況。
$lastYear = [ 6345.75, 9839.45, 7134.60, 9479.50, 9928.0, 8652.00, 7658.40, 10245.40, 7889.40, 3892.40, 3638.40, 2339.40 ]; $thisYear = [ 6145.75, 6895.00, 3434.00, 9349350, 9478.60, 7652.80, 4758.40, 10945.40, 3689.40, 8992.40, 7588.40, 2239.40 ];1.傳統的foreach 方式:
$profit = []; foreach($thisYear as $key => $monthly){ $profit[$key] = $monthly - $lastYear[$key]; } var_dump($profit);2.使用集合的zip、first、last:
$profit = collect($thisYear)->zip($lastYear)->map(function($monthly){ return $monthly->first() - $monthly->last(); });
zip:將給定陣列的值與相應索引處的原集合的值合併在一起。
建立lookup 陣列
需求:將如下陣列格式化成下面的結果:
$employees = [ [ 'name' => 'example', 'email' => 'example@exmaple.com', 'company' => 'example Inc.' ], [ 'name' => 'Lucy', 'email' => 'lucy@example.com', 'company' => 'ibm Inc.' ], [ 'name' => 'Taylor', 'email' => 'toylor@laravel.com', 'company'=>'Laravel Inc.' ] ]; // 格式化之後的結果 $lookup = [ 'example' => 'example@example.com', 'Lucy' => ‘lucy@example.com’, 'Taylor'=> 'toylor@laravel.com' ];1.傳統的foreach 方式:
$emails = []; foreach ($employees as $key => $value) { $emails[$value['name']] = $value['email']; }2.使用集合的reduce 方法:
$emails = collect($employees)->reduce(function($emailLookup, $employee){ $emailLookup[$employee['name']] = $employee['email']; return $emailLookup; },[]);
reduce:將每次迭代的結果傳遞給下一次迭代直到集合減少為單個值。
3.使用集合的pluck 方法:$emails = collect($employees)->pluck('name', 'email');