iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 20
1
自我挑戰組

Laravel 實戰經驗分享系列 第 20

Laravel 實戰經驗分享 - Day20 Laravel 的自創型別 Collections

活動終於倒數十天啦~~
這二十天來中累積了一點點的成果,雖然每天下班寫文章很煎熬,不過其實也養成一個快速整理知識的習慣了,的確收穫頗豐(但還是好想趕快完賽 R)

今晚,我想來點 Laravel 的 Collection

Collection(集合)是 Laravel 的一個自創型別,如果我們將它 dump 下來,可以發現他是 PHP 的 object 型別,而 Collection 可以將你的陣列(array)進行方便且流暢的運用。

$collection = collect([1,2,3]);
var_dump($collection);
object(Illuminate\Support\Collection)[262]
  protected 'items' => 
    array (size=3)
      0 => int 1
      1 => int 2
      2 => int 3

看起來是不是跟一般的陣列很像呢?
但是 Collection 方便的地方更多了,我們在前面幾篇提到的 ORM 方法,在 Collection 都可以使用。

  • all() 顯示 Collection 中的所有元素
$collection = collect([1,2,3]);
var_dump($collection->all());
array (size=3)
  0 => int 1
  1 => int 2
  2 => int 3
  • first() 取第一筆資料
$collection = collect([
    ['student' => 'Leo', 'number' => 1],
    ['student' => 'Peter', 'number' => 2],
    ['student' => 'David', 'number' => 3],
    ['student' => 'Vivian', 'number' => 4],
    ['student' => 'Jill', 'number' => 5]
]);
var_dump($collection->first());
array (size=2)
  'student' => string 'Leo' (length=3)
  'number' => int 1
  • where() 條件選取
$collection = collect([
    ['student' => 'Leo', 'number' => 1],
    ['student' => 'Peter', 'number' => 2],
    ['student' => 'David', 'number' => 3],
    ['student' => 'Vivian', 'number' => 4],
    ['student' => 'Jill', 'number' => 5]
]);
var_dump($collection->where('number', '>=', 3));
array (size=3)
2 => 
array (size=2)
  'student' => string 'David' (length=5)
  'number' => int 3
3 => 
array (size=2)
  'student' => string 'Vivian' (length=6)
  'number' => int 4
4 => 
array (size=2)
  'student' => string 'Jill' (length=4)
  'number' => int 5

我覺得 Collection 的方便在於讓陣列跟資料庫都可以有一致方法處理,因此在 Laravel 中,可以多善用 Collection,讓你處理資料更順暢。

更多 Collection 處理資料的方式可以參照官方文件

map()

這個方法是我在執行專案時常會用到的 Collection 方法,他有很多不同的用法。

  • 當迴圈使用

如果你的資料集需要逐筆進行處理的話,我們之前都是使用 foreach 進行處理,現在用 map() 就可以完成這個功能囉!

$collection = collect([
    ['student' => 'Leo', 'number' => 1],
    ['student' => 'Peter', 'number' => 2],
    ['student' => 'David', 'number' => 3],
    ['student' => 'Vivian', 'number' => 4],
    ['student' => 'Jill', 'number' => 5]
]);
var_dump($collection->map(function ($value) {
    $value['number'] *= 2;
    return $value;
}));
array (size=5)
0 => 
array (size=2)
  'student' => string 'Leo' (length=3)
  'number' => int 2
1 => 
array (size=2)
  'student' => string 'Peter' (length=5)
  'number' => int 4
2 => 
array (size=2)
  'student' => string 'David' (length=5)
  'number' => int 6
3 => 
array (size=2)
  'student' => string 'Vivian' (length=6)
  'number' => int 8
4 => 
array (size=2)
  'student' => string 'Jill' (length=4)
  'number' => int 10
  • 需要設定條件跳出迴圈

以往的用法都是在迴圈內寫 break 來跳出迴圈,在這裡的用法則是可以使用 reject() 實現。
number 這個欄位是奇數則不執行 map() 內的動作。

$collection = collect([
    ['student' => 'Leo', 'number' => 1],
    ['student' => 'Peter', 'number' => 2],
    ['student' => 'David', 'number' => 3],
    ['student' => 'Vivian', 'number' => 4],
    ['student' => 'Jill', 'number' => 5]
]);
var_dump($collection->reject(function ($value) {
    return $value['number'] % 2 === 0;
})->map(function ($value) {
    return $value;
}));
array (size=3)
0 => 
array (size=2)
  'student' => string 'Leo' (length=3)
  'number' => int 1
2 => 
array (size=2)
  'student' => string 'David' (length=5)
  'number' => int 3
4 => 
array (size=2)
  'student' => string 'Jill' (length=4)
  'number' => int 5
  • map() 外的值放進去 function 進行處理

如果你今天想要將某個值傳入 map()

$x = 10;
$collection = collect([0, 1, 2]);
$collection = $collection->map(function ($value) {
    return $value * $x;
});

可能會看到下圖的這個錯誤。

奇怪?怎麼顯示找不到 $x 這個值呢?
這個錯誤可以使用匿名函數的方式將值放進函式內,用法跟 Javascript 滿像的,也是現代 PHP 的一個特點。

$x = 10;
$collection = collect([0, 1, 2]);
$collection = $collection->map(function ($value) use ($x) {
    return $value * $x;
});
var_dump($collection);

可以看見這個匿名函式發揮作用了。

array (size=3)
  0 => int 0
  1 => int 10
  2 => int 20

擴展 Collection 方法

除此之外,Laravel 也提供了擴展 Collection 的巨集方法,讓你可以透過客製化的方式,完成自己的函式,下面以官方文件為例。

use Illuminate\Support\Collection;
use Illuminate\Support\Str;

Collection::macro('toUpper', function () {
    return $this->map(function ($value) {
        return Str::upper($value);
    });
});

$collection = collect(['first', 'second']);

$upper = $collection->toUpper();

總之,Laravel 的 Collection 提供了許多不錯的資料處理方法,大致上的需求都能進行處理,至於要做到更深入的應用,可以參考官方文件,寫得非常齊全。

明天見囉!


上一篇
Laravel 實戰經驗分享 - Day19 PHPUnit 如何在你的 Laravel 專案中寫測試
下一篇
Laravel 實戰經驗分享 - Day21 Laravel File Storage
系列文
Laravel 實戰經驗分享30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言