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($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']);

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

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();

Користувацькі Колекції

Якщо ви хочете використовувати власний об'єкт 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
{
/**
* Створити новий екземпляр колекції Eloquent.
*
* @param array<int, \Illuminate\Database\Eloquent\Model> $models
* @return \Illuminate\Database\Eloquent\Collection<int, \Illuminate\Database\Eloquent\Model>
*/
public function newCollection(array $models = []): Collection
{
return new UserCollection($models);
}
}

Якщо ви визначили метод newCollection або додали атрибут CollectedBy до вашої моделі, ви отримаєте екземпляр вашої користувацької колекції кожного разу, коли Eloquent зазвичай повертав би екземпляр Illuminate\Database\Eloquent\Collection.

Якщо ви хочете використовувати власну колекцію для кожної моделі у вашому застосунку, вам слід визначити метод newCollection у базовому класі моделі, який розширюється всіма моделями вашого застосунку.