• Час читання ~9 хв
  • 01.03.2023

Вступ

Колекції Laravel дійсно потужні для роботи з масивами даних. Вони забезпечують плавний, зручний інтерфейс для виконання загальних операцій масиву, таких як фільтрація, форматування та перетворення даних. У цій публікації в блозі ми розглянемо деякі ключові функції колекцій Laravel і те, як їх можна використовувати для спрощення та впорядкування вашого коду.

Створення колекцій

Найпростішим способом створення колекції є передавання масиву до методу collect():

$collection = collect(1, 2, 3, 4, 5);

Під час роботи з красномовними моделями та конструктором запитів він також поверне колекцію за замовчуванням.

$users = User::query()
    ->where('is_active', true)
    ->get();

Фільтрація даних

Колекції Laravel мають багато різних методів, які дозволяють нам фільтрувати дані в наших колекціях. Я покажу вам деякі методи, які можна використовувати для цієї мети.

filter()

Це найпоширеніший метод фільтрування даних у наборі. Він видалить всі елементи, які повертаються помилковими для даного зворотного дзвінка.

$users = collect([
    ['name' => 'John Doe', 'is_active' => true],
    ['name' => 'Mary Doe', 'is_active' => true],
    ['name' => 'Peter Doe', 'is_active' => false],
]);

$filtered = $users->filter(fn ($user) => $user['is_active']);
// [
//     ['name' => 'John Doe', 'is_active' => true],
//     ['name' => 'Mary Doe', 'is_active' => true],
// ]

Ви також можете викликати метод filter() без будь-якого зворотного дзвінка. У цьому випадку він видалить усі елементи, які є помилковими/порожніми, як null, false, '', 0, [].

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

where()

Подібно до методу where(), який використовується для красномовних запитів, метод where() може бути використаний для фільтрації даних на основі ключа/значення.

$users = collect([
    ['name' => 'John Doe', 'age' => 15],
    ['name' => 'Mary Doe', 'age' => 20],
    ['name' => 'Peter Doe', 'age' => 30],
    ['name' => 'George Doe', 'age' => 20],
]);

$filtered = $users->where('age', 20);
// [
//     ['name' => 'Mary Doe', 'age' => 20],
//     ['name' => 'George Doe', 'age' => 20],
// ]

Ви також можете передати оператор порівняння як другий параметр, як і метод Eloquent where().

$users = collect([
    ['name' => 'John Doe', 'age' => 15],
    ['name' => 'Mary Doe', 'age' => 20],
    ['name' => 'Peter Doe', 'age' => 30],
    ['name' => 'George Doe', 'age' => 20],
]);

$filtered = $users->where('age', '>=', 20);
// [
//     ['name' => 'Mary Doe', 'age' => 20],
//     ['name' => 'Peter Doe', 'age' => 30],
//     ['name' => 'George Doe', 'age' => 20],
// ]

Майте на увазі, що метод where() просто перевіряє, чи значення однакове, а не тип, тому 20 і '20' будуть однаковими. Якщо потрібно перевірити значення та тип, можна натомість скористатися методом whereStrict().

Ви також можете фільтрувати для декількох значень за допомогою методу whereIn() та діапазону значень за допомогою методу whereBetween()

$users = collect([
    ['name' => 'John Doe', 'age' => 15],
    ['name' => 'Mary Doe', 'age' => 20],
    ['name' => 'Peter Doe', 'age' => 30],
    ['name' => 'George Doe', 'age' => 20],
]);

$filtered = $users->whereIn('age', [20, 30]);
// [
//     ['name' => 'Mary Doe', 'age' => 20],
//     ['name' => 'Peter Doe', 'age' => 30],
//     ['name' => 'George Doe', 'age' => 20],
// ]
$users = collect([
    ['name' => 'John Doe', 'age' => 15],
    ['name' => 'Mary Doe', 'age' => 20],
    ['name' => 'Peter Doe', 'age' => 30],
    ['name' => 'George Doe', 'age' => 20],
]);

$filtered = $users->whereBetween('age', [15, 20]);
// [
//     ['name' => 'John Doe', 'age' => 15],
//     ['name' => 'Mary Doe', 'age' => 20],
//     ['name' => 'George Doe', 'age' => 20],
// ]

Важливо зазначити, що ці методи не застосовують жодних змін до вихідної колекції, вони створюють абсолютно нову колекцію з відфільтрованими елементами.

first()

Цей метод повертає перший елемент колекції, який повертає значення true для вказаного зворотного виклику.

$users = collect([
    ['name' => 'John Doe', 'age' => 15],
    ['name' => 'Mary Doe', 'age' => 20],
    ['name' => 'Peter Doe', 'age' => 30],
]);

$filtered = $users->first(fn ($user) => $user['age'] > 18);
// ['name' => 'Mary Doe', 'age' => 20]

Ви також можете викликати перший() метод без будь-якого зворотного дзвінка. У цьому випадку він поверне перший пункт Колекції.

$users = collect([
    ['name' => 'John Doe', 'age' => 15],
    ['name' => 'Mary Doe', 'age' => 20],
    ['name' => 'Peter Doe', 'age' => 30],
]);

$filtered = $users->first(fn ($user) => $user['age'] > 18);
// ['name' => 'John Doe', 'age' => 15]

Якщо ви хочете залишити виняток, якщо результату не знайдено, ви можете замість цього використовувати метод firstOrFail(). У цьому випадку, якщо елемент не знайдено, він кине виняток Illuminate\Support\ItemNotFoundException.

last()

Цей метод повертає останній елемент набору, який повертає значення true для вказаного зворотного виклику.

$users = collect([
    ['name' => 'John Doe', 'age' => 15],
    ['name' => 'Mary Doe', 'age' => 20],
    ['name' => 'Peter Doe', 'age' => 30],
]);

$filtered = $users->last(fn ($user) => $user['age'] > 18);
// ['name' => 'Peter Doe', 'age' => 30]

Ви також можете викликати last() без будь-якого зворотного дзвінка. У цьому випадку він поверне останній елемент Колекції.

$users = collect([
    ['name' => 'John Doe', 'age' => 15],
    ['name' => 'Mary Doe', 'age' => 20],
    ['name' => 'Peter Doe', 'age' => 30],
]);

$filtered = $users->first(fn ($user) => $user['age'] > 18);
// ['name' => 'Peter Doe', 'age' => 30]

only()

Цей метод можна використовувати для фільтрації потрібних елементів із колекції на основі ключів.

$user = collect([
    'id' => 1,
    'name' => 'John Doe',
    'email' => '[email protected]
ї', 'username' => 'john_doe', ]); $filtered = $user->only(['name', 'email']); // ['name' => 'John Doe', 'email' => '[email protected]']

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

except()

Цей метод можна використовувати для фільтрування небажаних елементів із колекції на основі ключів.

$user = collect([
    'id' => 1,
    'name' => 'John Doe',
    'email' => '[email protected]',
    'username' => 'john_doe',
]);

$filtered = $user->except(['name', 'email']);
// ['id' => 1, 'username' => 'john_doe']

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

Форматування та перетворення даних

Досить часто програми отримують деякі дані, циклічно переглядають їх, щоб перетворити значення та перемістити відформатоване значення у тимчасову змінну. Замість того, щоб робити це, ми можемо використовувати метод map(), який виконає заданий зворотний виклик у кожному елементі Колекції та поверне нову Колекцію з перетвореними/відформатованими значеннями.

$users = collect([
    ['name' => 'John Doe', 'email' => '[email protected]', 'is_active' => true],
    ['name' => 'Mary Doe', 'email' => '[email protected]', 'is_active' => true],
    ['name' => 'Peter Doe', 'email' => '[email protected]', 'is_active' => true],
]);

$userModels = $users->map(fn ($user) => new User($user));

Налагодження колекцій Іноді нам

потрібно налагодити цінності наших колекцій, і колекції Laravel мають два методи з коробки, щоб допомогти нам у цьому.

dump()

Цей метод скидає елементи колекції та продовжує виконувати сценарій.

dd()

Цей метод скидає елементи Collection і закінчує виконання сценарію.

Приховані дорогоцінні камені

Крім методів, вже представлених в розділах вище. Є деякі методи, які не використовуються так багато або не дуже відомі, але це може змінити гру залежно від того, над чим ми працюємо. Нижче я перерахую деякі методи, які, на мою думку, ви повинні знати.

undot()

Цей метод може бути використаний для перетворення точкових рядків в масиви.

$data = collect([
    'user.first_name' => 'John',
    'user.last_name' => 'Doe',
    'user.email' => '[email protected]',
    'user.social.twitter' => '@john_doe',
    'user.social.github' => 'JohnDoe',
]);

$user = $data->undot();
// [
//     "user" => [
//         "first_name" => "John",
//         "last_name" => "Doe",
//         "email" => "[email protected]",
//         "social" => [
//             "twitter" => '@john_doe',
//             "github" => 'JohnDoe',
//         ],
//     ],
// ]

partition()

Цей метод розділяє елементи Колекції на два різних на основі заданого зворотного дзвінка. Товари, які повертаються вірними для даного зворотного дзвінка, будуть заштовхнуті в першу колекцію, а ті, що повертаються помилковими, будуть переміщені в другу.

$users = collect([
    ['name' => 'John Doe', 'is_active' => true],
    ['name' => 'Mary Doe', 'is_active' => false],
    ['name' => 'Peter Doe', 'is_active' => true],
]);

[$activeUsers, $inactiveUsers] = $users->partition(fn ($user) => $user['is_active']);

$activeUsers->all();
// [
//     ['name' => 'John Doe', 'is_active' => true],
//     ['name' => 'Peter Doe', 'is_active' => true],
// ]

$inactiveUsers->all();
// [
//     ['name' => 'Mary Doe', 'is_active' => false],
// ]

reject()

Це протилежність методу фільтра(), але він не такий відомий. Він видалить всі елементи, які повертаються вірними для даного зворотного дзвінка.

$users = collect([
    ['name' => 'John Doe', 'is_active' => true],
    ['name' => 'Mary Doe', 'is_active' => true],
    ['name' => 'Peter Doe', 'is_active' => false],
]);

$filtered = $users->reject(fn ($user) => $user['is_active']);
// [
//     ['name' => 'Peter Doe', 'is_active' => false],
// ]

random()

Цей метод повертає випадковий елемент із колекції.

$data = collect([1, 2, 3, 4, 5]);

$data->random();
// 3 - randomly selected

Якщо потрібно отримати більше одного елемента, можна передати ціле число як аргумент.

$data = collect([1, 2, 3, 4, 5]);

$data->random(2);
// [2, 3] - randomly selected

isEmpty()

Цей метод повертає значення true, якщо колекція не містить елементів, або хибність, якщо вона містить принаймні один елемент.

collect([])->isEmpty(); // true
collect([1])->isEmpty(); // false

isNotEmpty()

Цей метод протилежний методу isEmpty(). Він повернеться вірним, якщо в Колекції є хоча б один предмет, і помилковий, якщо на ньому немає жодних предметів. Повідомлення

collect([])->isNotEmpty(); // false
collect([1])->isNotEmpty(); // true

високого порядку

високого порядку are like shortcuts that we can use to apply common actions in our Collections. The methods that support this feature are: average(), avg(), contains(), each(), every(), filter(), first(), flatMap(), groupBy(), keyBy(), map(), max(), min(), partition(), reject(), skipUntil(), skipWhile(), some(), sortBy(), sortByDesc(), sum(), takeUntil(), takeWhile(), and unique().

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

User::query()
    ->where('receive_newsletter', true)
    ->each
    ->sendNewsletter();

 

Lazy Collections Collections дійсно потужні, і LazyCollections розширюють їх потужність за допомогою генераторів, тому ми можемо працювати з великими наборами даних, але зберігаючи низьке використання пам'яті.

Уявіть, що у нас є мільйони продуктів у нашій базі даних, і нам потрібно виконати деякі дії над ними, ми можемо використовувати метод cursor() від Eloquent/Query Builder, щоб повернути LazyCollection замість звичайної Колекції.

$payments = Payment::query()
    ->where('is_accepted', true)
    ->cursor()
    ->map(fn ($payment) => $this->formatPaymentData($payment));

foreach ($payments as $payment) {
    // LOGIC HERE
}

У наведеному вище прикладі один запит буде запущений проти бази даних, але він також буде зберігати в пам'яті лише один елемент одночасно. Крім того, зворотний дзвінок map() буде виконаний не відразу, а лише тоді, коли ми переглянемо кожен окремий елемент у заяві foreach.

Створення власних методів колекції

Окрім усіх дивовижних методів, які колекції вже мають із коробки, ми можемо створити власні методи, оскільки вони є "макропридатними". Це означає, що ми можемо використовувати метод макро() для їх розширення за допомогою власних методів. Для цього нам потрібно додати наші нові користувацькі методи в метод завантаження () класу AppServiceProvider.Висновок

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Collection::macro('toSlug', function () {
            return $this->map(fn ($value) => Str::slug($value, '-'));
        });
    }
}

.


Це лише кілька прикладів багатьох потужних методів, доступних у колекціях Laravel. Використовуючи ці методи, ви можете легко та ефективно маніпулювати своїми даними, роблячи ваш код більш читабельним та ремонтопридатним.

Сподіваюся, що вам сподобалася ця стаття, і якщо ви це зробите, не забудьте поділитися цією статтею зі своїми друзями!!! Бувай! :wink:

Останнє оновлення 1 місяць тому.

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

Про мене

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

Про автора CrazyBoy49z
WORK EXPERIENCE
Контакти
Ukraine, Lutsk
+380979856297