Eloquent:Collection
簡介
Eloquent 中,所有回傳多筆 Model 結果的方法都會回傳 Illuminate\Database\Eloquent\Collection
的實體,這些方法包含 get
方法或是以關聯進行存取時。Eloquent Collection 物件繼承自 Laravel 的基礎 Collection,因此,這些 Collection 也自然繼承了數十種可用來流暢地操作底層 Eloquent Model 陣列的方法。記得看看 Laravel Collection 說明文件來了解這些實用的方法!
所有的 Collection 也可作為迭代器使用,因此你可以很輕鬆地像迭代一般 PHP 陣列一樣迭代這些 Collection:
1use App\Models\User;23$users = User::where('active', 1)->get();45foreach ($users as $user) {6 echo $user->name;7}
1use App\Models\User;23$users = User::where('active', 1)->get();45foreach ($users as $user) {6 echo $user->name;7}
不過,剛才也提到過,Collection 比起陣列來說多了很多更強大的功能。而且,Collection 也提供了多種可通過直觀介面串連使用的各個 map / reduce 操作。舉例來說,我們可以將所有非啟用狀態的 Model 移除,並取得剩餘使用者的名字:
1$names = User::all()->reject(function (User $user) {2 return $user->active === false;3})->map(function (User $user) {4 return $user->name;5});
1$names = User::all()->reject(function (User $user) {2 return $user->active === false;3})->map(function (User $user) {4 return $user->name;5});
Eloquent Collection 轉換
雖然大多數的 Eloquent Collection 方法都會回傳新的 Eloquent Collection 實體,但 collapse
, flatten
, flip
, keys
, pluck
, 與 zip
方法都會回傳基礎 collection實體。同樣地,若 map
操作回傳不包含任何 Eloquent Model 的實體,則會回傳基礎 Collection 實體。
可用方法
所有的 Eloquent Collection 都繼承自基礎 Laravel Collection 物件。因此,這些 Collection 都繼承了基礎 Collection 類別所提供的所有強大方法。
除此之外,Illuminate\Database\Eloquent\Collection
類別還提供了一組可用來處理 Model Collection 的方法。大多數的方法都會回傳 Illuminate\Database\Eloquent\Collection
實體。不過,有些如 modelKeys
之類的方法則會回傳 Illuminate\Support\Collection
實體。
append contains diff except find findOrFail fresh intersect load loadMissing modelKeys makeVisible makeHidden only setVisible setHidden toQuery unique
append($attributes)
append
方法可用來表示某個屬性應被附加到該 Collection 中的每個 Model 上。可傳入一組屬性陣列或單一屬性給該方法:
1$users->append('team');23$users->append(['team', 'is_admin']);
1$users->append('team');23$users->append(['team', 'is_admin']);
contains($key, $operator = null, $value = null)
contains
方法可用來判斷給定的 Model 實體是否包含在該 Collection 內。該方法可接受主鍵 (Primary Key) 或 Model 實體:
1$users->contains(1);23$users->contains(User::find(1));
1$users->contains(1);23$users->contains(User::find(1));
diff($items)
diff
方法會回傳所有不存在給定 Collection 中的所有 Model:
1use App\Models\User;23$users = $users->diff(User::whereIn('id', [1, 2, 3])->get());
1use App\Models\User;23$users = $users->diff(User::whereIn('id', [1, 2, 3])->get());
except($keys)
except
方法會回傳沒有給定主鍵的所有 Model:
1$users = $users->except([1, 2, 3]);
1$users = $users->except([1, 2, 3]);
find($key)
find
方法會回傳主鍵符合給定索引鍵的 Model。若 $key
為 Model 實體,則 find
會嘗試回傳符合該主鍵的 Model。若 $key
為一組索引鍵的陣列,則 find
會回傳所有主鍵包含在給定陣列中的 Model:
1$users = User::all();23$user = $users->find(1);
1$users = User::all();23$user = $users->find(1);
findOrFail($key)
The findOrFail
method returns the model that has a primary key matching the given key or throws an Illuminate\Database\Eloquent\ModelNotFoundException
exception if no matching model can be found in the collection:
1$users = User::all();23$user = $users->findOrFail(1);
1$users = User::all();23$user = $users->findOrFail(1);
fresh($with = [])
fresh
方法會從資料庫中取得該 Collection 中各個 Model 的最新實體 (Fresh Instance)。此外,若有指定關聯,則會積極式載入 (Eager Loading) 這些關聯:
1$users = $users->fresh();23$users = $users->fresh('comments');
1$users = $users->fresh();23$users = $users->fresh('comments');
intersect($items)
diff
方法會回傳所有同時存在於給定 Collection 中的所有 Model:
1use App\Models\User;23$users = $users->intersect(User::whereIn('id', [1, 2, 3])->get());
1use App\Models\User;23$users = $users->intersect(User::whereIn('id', [1, 2, 3])->get());
load($relations)
load
方法會積極式載入 (Eager Loading) Collection 中所有 Model 上的給定關聯:
1$users->load(['comments', 'posts']);23$users->load('comments.author');45$users->load(['comments', 'posts' => fn ($query) => $query->where('active', 1)]);
1$users->load(['comments', 'posts']);23$users->load('comments.author');45$users->load(['comments', 'posts' => fn ($query) => $query->where('active', 1)]);
loadMissing($relations)
loadMissing
方法會在該 Collection 中所有 Model 的給定關聯尚未載入時將其積極式載入 (Eager Loading):
1$users->loadMissing(['comments', 'posts']);23$users->loadMissing('comments.author');45$users->loadMissing(['comments', 'posts' => fn ($query) => $query->where('active', 1)]);
1$users->loadMissing(['comments', 'posts']);23$users->loadMissing('comments.author');45$users->loadMissing(['comments', 'posts' => fn ($query) => $query->where('active', 1)]);
modelKeys()
modelKeys
方法會回傳該 Collection 中所有方法的主鍵:
1$users->modelKeys();23// [1, 2, 3, 4, 5]
1$users->modelKeys();23// [1, 2, 3, 4, 5]
makeVisible($attributes)
makeVisible
方法會將該 Collection 中所有 Model 上通常「隱藏 (Hidden)」的屬性設為可見:
1$users = $users->makeVisible(['address', 'phone_number']);
1$users = $users->makeVisible(['address', 'phone_number']);
makeHidden($attributes)
makeHidden
方法會將該 Collection 中所有 Model 上通常「可見 (Visible)」的屬性設為隱藏:
1$users = $users->makeHidden(['address', 'phone_number']);
1$users = $users->makeHidden(['address', 'phone_number']);
only($keys)
except
方法會回傳符合給定主鍵的所有 Model:
1$users = $users->only([1, 2, 3]);
1$users = $users->only([1, 2, 3]);
setVisible($attributes)
setVisible
方法可暫時複寫掉該 Collection 中各個 Model 的所有 visible 屬性:
1$users = $users->setVisible(['id', 'name']);
1$users = $users->setVisible(['id', 'name']);
setHidden($attributes)
setHidden
方法可暫時複寫掉該 Collection 中各個 Model 的所有 hidden 屬性:
1$users = $users->setHidden(['email', 'password', 'remember_token']);
1$users = $users->setHidden(['email', 'password', 'remember_token']);
toQuery()
toQuery
方法回傳 Eloquent Query Builder 實體,並包含了由該 Collection 中 Model 的主索引鍵所組成的 whereIn
限制式:
1use App\Models\User;23$users = User::where('status', 'VIP')->get();45$users->toQuery()->update([6 'status' => 'Administrator',7]);
1use App\Models\User;23$users = User::where('status', 'VIP')->get();45$users->toQuery()->update([6 'status' => 'Administrator',7]);
unique($key = null, $strict = false)
The unique
method returns all of the unique models in the collection. Any models with the same primary key as another model in the collection are removed:
1$users = $users->unique();
1$users = $users->unique();
自訂 Collection
If you would like to use a custom Collection
object when interacting with a given model, you may add the CollectedBy
attribute to your model:
1<?php23namespace App\Models;45use App\Support\UserCollection;6use Illuminate\Database\Eloquent\Attributes\CollectedBy;7use Illuminate\Database\Eloquent\Model;89#[CollectedBy(UserCollection::class)]10class User extends Model11{12 // ...13}
1<?php23namespace App\Models;45use App\Support\UserCollection;6use Illuminate\Database\Eloquent\Attributes\CollectedBy;7use Illuminate\Database\Eloquent\Model;89#[CollectedBy(UserCollection::class)]10class User extends Model11{12 // ...13}
Alternatively, you may define a newCollection
method on your model:
1<?php23namespace App\Models;45use App\Support\UserCollection;6use Illuminate\Database\Eloquent\Collection;7use Illuminate\Database\Eloquent\Model;89class User extends Model10{11 /**12 * Create a new Eloquent Collection instance.13 *14 * @param array<int, \Illuminate\Database\Eloquent\Model> $models15 * @return \Illuminate\Database\Eloquent\Collection<int, \Illuminate\Database\Eloquent\Model>16 */17 public function newCollection(array $models = []): Collection18 {19 return new UserCollection($models);20 }21}
1<?php23namespace App\Models;45use App\Support\UserCollection;6use Illuminate\Database\Eloquent\Collection;7use Illuminate\Database\Eloquent\Model;89class User extends Model10{11 /**12 * Create a new Eloquent Collection instance.13 *14 * @param array<int, \Illuminate\Database\Eloquent\Model> $models15 * @return \Illuminate\Database\Eloquent\Collection<int, \Illuminate\Database\Eloquent\Model>16 */17 public function newCollection(array $models = []): Collection18 {19 return new UserCollection($models);20 }21}
Once you have defined a newCollection
method or added the CollectedBy
attribute to your model, you will receive an instance of your custom collection anytime Eloquent would normally return an Illuminate\Database\Eloquent\Collection
instance.
If you would like to use a custom collection for every model in your application, you should define the newCollection
method on a base model class that is extended by all of your application's models.