對許多初學者來說,「PHP 中的 Array」和「Laravel 中的 Collection」這兩者的差異可能不是那麼明顯。這篇文章將帶大家一探究竟,介紹這兩者的不同點,以及各自的優缺點。
Array
在 PHP 中,Array 是一種原生的資料結構,實際上它並不算是一個物件類型,而是一種儲存資料的方式,可以包含數字索引或關聯索引的元素。PHP 提供了許多內建的函數來操作 Array,像是 array_map()
、array_filter()
等等。
Collection
在 Laravel 中,Collection 是一個強大的資料處理工具,它是基於 PHP Array 之上進行擴展的。Laravel 提供了許多便捷的 Collection 方法,像是 map()
、filter()
、reduce()
等等,可以幫助高效地處理資料,但缺點是一定得用 Laravel 框架。
兩者間的差異
除了前面提到的原生與框架依賴的差別,以下是 Array 與 Collection 之間的其他主要區別:
- 本質不同:
Array 僅是一種基本的資料結構,通常用來儲存一組數據。而 Collection 則可以視為一個擁有方法的物件,並且支持封裝、繼承等物件導向特性,讓它在處理複雜資料時更具彈性與擴展性。 - 方法連鎖(Method Chaining):
由於 Array 是 PHP 的原生資料結構,它的操作方法是分開的,無法進行鏈式呼叫(Method Chaining),每次呼叫都需要依序處理。例如,操作 Array 時可能需要寫成:$result = array_filter(array_map(...));
而 Collection 則可以鏈式呼叫多個方法,讓程式碼更加簡潔與易讀。例如,對一個 Collection 使用多個方法時,可以這樣寫:$collection->filter(...)->map(...)->sort(...);
這樣的寫法讓程式碼更具可讀性,也更容易維護。 - 高階方法:
Collection 提供了許多高階方法,這些方法使得程式碼更加簡潔並提升開發效率。例如,若需要取得資料集的第一筆資料,使用 Collection 可以直接寫:$firstItem = $collection->head();
相對而言,對於原生的 Array,則需要更多的程式碼來實現相同的功能,可能要用reset($array)
或array_slice($array, 0, 1)
來取出第一筆資料。 - Eloquent 互動:
Collection 在 Laravel 中有與 Eloquent 查詢結果集成的特性。這意味著,從 Eloquent 查詢結果取得的資料就是一個 Collection,你可以直接在查詢結果上鏈式呼叫 Collection 方法來進行處理。例如:
這種集成性使得操作查詢結果變得更加靈活且直觀。$users = User::where('active', 1)->get(); // 返回 Collection
$names = $users->pluck('name');
整體來說,雖然 Collection 因為有許多高階方法讓使用上更方便,但其實使用後的效能不一定更好。在一些僅需要小數據的操作時,或許 Array 才是使用上比較好的選擇喔。
collect()的用法
Collection 本身可以直接帶入 Array 的資料進行建立。
$a = ['key' => 'value'];
$ac = collect($a); // 會建立 'key' => 'value' 的 Collection
此時,你需要確認帶入的 Array 是否為空,以及你想要什麼結果。
$b = [];
$bc1 = collect($a); // 返回一個空的 Collection,內部無元素,通過 isEmpty() 確認為 true
$bc2 = collect([$a]); //返回一個包含一個空数组的 Collection,内部有一個元素
同理,處理空類別的方式也是同樣的方式。
Class myClass {
public string $name;
public string $value;
}
$cc1 = collect(myClass::empty()); // 會解離每一個屬性包成 Array,不再擁有 myClass 這個類別
dump($cc1);
/*
....Illuminate\\Support\\Collection^ {
#items: array:6 [
"\\x00App\\myClass\\x00name" => ""
"\\x00App\\myClass\\x00email" => ""
"\\x00App\\ValueObjects\\Csr\\CsrEmployee\\x00value" => ""
]
#escapeWhenCastingToString: false
}
*/
$cc2 = collect([myClass::empty()]); // 保有 myClass 這個類別,直接視為一整個物件
dump($cc2);
/*
....Illuminate\\Support\\Collection^ {
#items: array:1 [
0 => App\\myClass^ {
-name: ""
-value: ""
}
]
#escapeWhenCastingToString: false
}
*/
由以上可以發現不同代入方式會取得不同的結果,要特別注意。
用 map 去調整組成 Collection 的內容
有時候雖然 Array 中擁有所有必要的資訊,但直接塞入 Collection 並非最理想的結果,我們可能會希望先做些調整與計算再塞入 Collection ,此時就可以搭配 map 作使用。
舉例來說,如果我們想改變 Collection 內儲存的結構,可以作如下的調整:
$a = collect($rawData)
->map(
function (array $data) {
$b = $data['one'] + $data['two'];
$c = $data['msg'] ?? '';
return new OtherCalss(
$b,
$c,
Type::from($data['type']),
Carbon::parse($data['now']),
null,
collect(),
);
});
這次就介紹到這邊,我們下次再見!