Eloquent: колекції
Вступ
Усі методи Eloquent, що повертають більш ніж одну модель, повертають екземпляри класу Illuminate\Database\Eloquent\Collection - зокрема й результати методу get та отримані через зв'язок. Об'єкт колекції Eloquent розширює базову колекцію Laravel, тож він природно успадковує десятки методів для плавної роботи з масивом моделей Eloquent, що лежить у його основі. Обов'язково перегляньте документацію з колекцій Laravel, щоб дізнатися про всі ці корисні методи!
Усі колекції є також ітераторами, тож ви можете обходити їх у циклі, наче звичайні PHP-масиви:
use App\Models\User;
$users = User::where('active', 1)->get();
foreach ($users as $user) {
echo $user->name;
}
Проте, як уже згадувалося, колекції значно потужніші за масиви й дають цілу низку операцій map / reduce, які можна зчіплювати ланцюжком через інтуїтивний інтерфейс. Наприклад, ми можемо прибрати всі неактивні моделі, а потім зібрати імена решти користувачів:
$names = User::all()->reject(function (User $user) {
return $user->active === false;
})->map(function (User $user) {
return $user->name;
});
Перетворення колекцій Eloquent
Хоча більшість методів колекції Eloquent повертають новий екземпляр колекції Eloquent, методи collapse, flatten, flip, keys, pluck і zip повертають екземпляр базової колекції. Так само, якщо операція map повертає колекцію, у якій немає жодної моделі Eloquent, її буде перетворено на екземпляр базової колекції.
Доступні методи
Усі колекції Eloquent розширюють об'єкт базової колекції Laravel, тож успадковують усі потужні методи базового класу колекцій.
Крім того, клас Illuminate\Database\Eloquent\Collection має надмножину методів для роботи з колекціями ваших моделей. Більшість методів повертають екземпляри Illuminate\Database\Eloquent\Collection; проте деякі - як-от modelKeys - повертають екземпляр Illuminate\Support\Collection.
append contains diff except find findOrFail fresh intersect load loadMissing modelKeys makeVisible makeHidden mergeVisible mergeHidden only partition setAppends setVisible setHidden toQuery unique withoutAppends
append($attributes)
Методом append можна вказати, що атрибут слід додавати для кожної моделі в колекції. Метод приймає масив атрибутів або один атрибут:
$users->append('team');
$users->append(['team', 'is_admin']);
contains($key, $operator = null, $value = null)
Методом contains можна визначити, чи міститься в колекції заданий екземпляр моделі. Метод приймає первинний ключ або екземпляр моделі:
$users->contains(1);
$users->contains(User::find(1));
diff($items)
Метод diff повертає всі моделі, яких немає в заданій колекції:
use App\Models\User;
$users = $users->diff(User::whereIn('id', [1, 2, 3])->get());
except($keys)
Метод except повертає всі моделі, які не мають заданих первинних ключів:
$users = $users->except([1, 2, 3]);
find($key)
Метод find повертає модель, первинний ключ якої збігається із заданим. Якщо $key - екземпляр моделі, find спробує повернути модель із таким самим первинним ключем. Якщо $key - масив ключів, find поверне всі моделі, чиї первинні ключі є в цьому масиві:
$users = User::all();
$user = $users->find(1);
findOrFail($key)
Метод findOrFail повертає модель, первинний ключ якої збігається із заданим, або викидає виняток Illuminate\Database\Eloquent\ModelNotFoundException, якщо відповідної моделі в колекції немає:
$users = User::all();
$user = $users->findOrFail(1);
fresh($with = [])
Метод fresh дістає з бази даних свіжий екземпляр кожної моделі в колекції. Крім того, будь-які вказані зв'язки буде жадібно завантажено:
$users = $users->fresh();
$users = $users->fresh('comments');
intersect($items)
Метод intersect повертає всі моделі, які є також у заданій колекції:
use App\Models\User;
$users = $users->intersect(User::whereIn('id', [1, 2, 3])->get());
load($relations)
Метод load жадібно завантажує задані зв'язки для всіх моделей у колекції:
$users->load(['comments', 'posts']);
$users->load('comments.author');
$users->load(['comments', 'posts' => fn ($query) => $query->where('active', 1)]);
loadMissing($relations)
Метод loadMissing жадібно завантажує задані зв'язки для всіх моделей у колекції, якщо ці зв'язки ще не завантажено:
$users->loadMissing(['comments', 'posts']);
$users->loadMissing('comments.author');
$users->loadMissing(['comments', 'posts' => fn ($query) => $query->where('active', 1)]);
modelKeys()
Метод modelKeys повертає первинні ключі всіх моделей у колекції:
$users->modelKeys();
// [1, 2, 3, 4, 5]
makeVisible($attributes)
Метод makeVisible робить видимими атрибути, які зазвичай «приховані» в кожній моделі колекції:
$users = $users->makeVisible(['address', 'phone_number']);
makeHidden($attributes)
Метод makeHidden приховує атрибути, які зазвичай «видимі» в кожній моделі колекції:
$users = $users->makeHidden(['address', 'phone_number']);
mergeVisible($attributes)
Метод mergeVisible робить видимими додаткові атрибути, зберігаючи наявні видимі атрибути:
$users = $users->mergeVisible(['middle_name']);
mergeHidden($attributes)
Метод mergeHidden приховує додаткові атрибути, зберігаючи наявні приховані атрибути:
$users = $users->mergeHidden(['last_login_at']);
only($keys)
Метод only повертає всі моделі, які мають задані первинні ключі:
$users = $users->only([1, 2, 3]);
partition
Метод partition повертає екземпляр Illuminate\Support\Collection, що містить екземпляри колекцій Illuminate\Database\Eloquent\Collection:
$partition = $users->partition(fn ($user) => $user->age > 18);
dump($partition::class); // Illuminate\Support\Collection
dump($partition[0]::class); // Illuminate\Database\Eloquent\Collection
dump($partition[1]::class); // Illuminate\Database\Eloquent\Collection
setAppends($attributes)
Метод setAppends тимчасово перевизначає всі додані атрибути кожної моделі в колекції:
$users = $users->setAppends(['is_admin']);
setVisible($attributes)
Метод setVisible тимчасово перевизначає всі видимі атрибути кожної моделі в колекції:
$users = $users->setVisible(['id', 'name']);
setHidden($attributes)
Метод setHidden тимчасово перевизначає всі приховані атрибути кожної моделі в колекції:
$users = $users->setHidden(['email', 'password', 'remember_token']);
toQuery()
Метод toQuery повертає екземпляр конструктора запитів Eloquent з обмеженням whereIn за первинними ключами моделей колекції:
use App\Models\User;
$users = User::where('status', 'VIP')->get();
$users->toQuery()->update([
'status' => 'Administrator',
]);
unique($key = null, $strict = false)
Метод unique повертає всі унікальні моделі колекції. Моделі з таким самим первинним ключем, як в іншої моделі колекції, буде прибрано:
$users = $users->unique();
withoutAppends()
Метод withoutAppends тимчасово прибирає всі додані атрибути кожної моделі в колекції:
$users = $users->withoutAppends();
Власні колекції
Якщо ви хочете використовувати власний об'єкт Collection під час роботи з певною моделлю, додайте до неї атрибут CollectedBy:
<?php
namespace App\Models;
use App\Support\UserCollection;
use Illuminate\Database\Eloquent\Attributes\CollectedBy;
use Illuminate\Database\Eloquent\Model;
#[CollectedBy(UserCollection::class)]
class User extends Model
{
// ...
}
Або ж ви можете описати в моделі метод newCollection:
<?php
namespace App\Models;
use App\Support\UserCollection;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Create a new Eloquent Collection instance.
*
* @param array<int, \Illuminate\Database\Eloquent\Model> $models
* @return \Illuminate\Database\Eloquent\Collection<int, \Illuminate\Database\Eloquent\Model>
*/
public function newCollection(array $models = []): Collection
{
$collection = new UserCollection($models);
if (Model::isAutomaticallyEagerLoadingRelationships()) {
$collection->withRelationshipAutoloading();
}
return $collection;
}
}
Коли ви описали метод newCollection або додали до моделі атрибут CollectedBy, ви отримуватимете екземпляр власної колекції щоразу, коли Eloquent зазвичай повернув би екземпляр Illuminate\Database\Eloquent\Collection.
Якщо ви хочете використовувати власну колекцію для кожної моделі у вашому застосунку, опишіть метод newCollection у базовому класі моделі, який розширюють усі моделі вашого застосунку.