This note is used to organize the actual application scenarios of Collection in Laravel.
Summing
Requirement: Traverse the $orders array and find the sum of prices.
<?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. Use the traditional foreach method to traverse:
$sum = 0; foreach ($orders as $order) { foreach ($order['order_products'] as $item) { $sum += $item['price']; } } echo $sum;2. Use the map, flatten, and sum of the collection:
$sum = collect($orders)->map(function($order){ return $order['order_products']; })->flatten(1)->map(function($order){ return $order['price']; })->sum(); echo $sum;
map: Traverse the collection and return a new collection.
flatten: Convert a multidimensional array to one dimension.
sum: Returns the sum of the array.
$sum = collect($orders)->flatMap(function($order){ return $order['order_products']; })->pluck('price')->sum(); echo $sum;
flatMap: Similar to map
, but the difference is that flatMap
can directly use the returned new collection.
$sum = collect($orders)->flatMap(function($order){ return $order['order_products']; })->sum('price');
sum: You can receive a column name as a parameter for summation.
Formatting data
Requirements: Format the array with the following structure into the new array below.
// 带格式化数组 $gates = [ 'BaiYun_A_A17', 'BeiJing_J7', 'ShuangLiu_K203', 'HongQiao_A157', 'A2', 'BaiYun_B_B230' ]; // 新数组 $boards = [ 'A17', 'J7', 'K203', 'A157', 'A2', 'B230' ];1. Use foreach to traverse:
$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. Use the map of the collection and the explode and end of php:
$res = collect($gates)->map(function($gate) { $parts = explode('_', $gate); return end($parts); });3. Use the map, explode, last, and toArray of the collection:
$res = collect($gates)->map(function($gate) { return collect(explode('_', $gate))->last(); })->toArray();
explode: Split the string into an array
last: Get the last element
Statistics GitHub Event
First, get the personal event json through this link.
One PushEvent is worth
5 points, one CreateEvent
is worth 4 points, one IssueCommentEvent is worth
3 points, one IssueCommentEvent
It is worth 2 points, other types of events are worth 1 point, and the total time score of the current user is calculated.
$opts = [ 'http' => [ 'method' => 'GET', 'header' => [ 'User-Agent: PHP' ] ] ]; $context = stream_context_create($opts); $events = json_decode(file_get_contents('http://api.github.com/users/0xAiKang/events', false, $context), true);1. Traditional foreach method:
$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. Use the map, pluck, and sum methods of the set:
$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();
Using chain programming of the set can well solve the above multiple traversal problems.
3. Use the map, pluck, and get methods in the collection:$score = $events->pluck('type')->map(function($eventType) { return collect([ 'PushEvent'=> 5, 'CreateEvent'=> 4, 'IssueEvent'=> 3, 'IssueCommentEvent'=> 2 ])->get($eventType, 1); // 如果不存在则默认等于1 })->sum();4. Try to encapsulate this requirement into a class:
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));
Format data
Requirement: The following data is formatted into a new structure.
$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. Traditional foreach method:
$comment = '- ' . array_shift($messages); foreach ($messages as $message) { $comment .= "\n - ${message}"; } var_dump($comment);2. Use the map and implode methods of the set:
$comment = collect($messages)->map(function($message){ return '- ' . $message; })->implode("\n"); var_dump($comment);
Multiple arrays to find differences
Requirements: Two sets of data represent last year's data respectively Revenue and this year's revenue, find the profit and loss for each month.
$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. Traditional foreach method:
$profit = []; foreach($thisYear as $key => $monthly){ $profit[$key] = $monthly - $lastYear[$key]; } var_dump($profit);2. Use zip, first, last of the collection:
$profit = collect($thisYear)->zip($lastYear)->map(function($monthly){ return $monthly->first() - $monthly->last(); });
zip: Merge the values of the given array with the values of the original collection at the corresponding index.
Create a lookup array
Requirements: Format the following array into the following result:
$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. Traditional foreach method:
$emails = []; foreach ($employees as $key => $value) { $emails[$value['name']] = $value['email']; }2. Use the reduce method of the set:
$emails = collect($employees)->reduce(function($emailLookup, $employee){ $emailLookup[$employee['name']] = $employee['email']; return $emailLookup; },[]);
reduce: Pass the result of each iteration to the next iteration until the set is reduced to a single value.
3. Use the pluck method of collection:$emails = collect($employees)->pluck('name', 'email');