• Время чтения ~9 мин
  • 01.03.2023

Введение

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

Создание

коллекций Самый простой способ создать коллекцию — передать массив методу collect():

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

При работе с Eloquent Models и построителем запросов он также будет возвращать коллекцию по умолчанию.

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

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

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

filter()

Это наиболее распространенный метод фильтрации данных в коллекции. Он удалит все элементы, которые возвращают false для заданного обратного вызова.

$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(), используемый для запросов 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' => '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()

Этот метод возвращает первый элемент коллекции Collection, который возвращает значение 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]

Можно также вызвать метод first() без обратного вызова. В этом случае он вернет первый предмет Коллекции.

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

Этот метод возвращает последний элемент коллекции Collection, возвращающий значение 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()

Этот метод создает дамп элементов Collection и продолжает выполнение скрипта.

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

Этот метод разделяет элементы Collection на два разных элемента на основе заданного обратного вызова. Элементы, которые возвращают true для данного обратного вызова, будут отправлены в первую коллекцию, а те, которые возвращают false, будут отправлены во вторую.

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

Это противоположно методу filter(), но он не так хорошо известен. Он удалит все элементы, возвращающие значение true для заданного обратного вызова.

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

Этот метод возвращает случайный элемент из коллекции Collection.

$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, если в коллекции нет элементов, или значение false, если в нем есть хотя бы один элемент.

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

isNotEmpty()

Этот метод противоположен методу isEmpty(). Он вернет значение true, если в коллекции есть хотя бы один элемент, и значение false, если в нем нет элементов.

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 действительно мощные, и 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.

Создание собственных методов коллекции

Помимо всех удивительных методов, которые уже есть в коллекциях из коробки, мы можем создавать наши собственные методы, поскольку они являются «макросъемными». Это означает, что мы можем использовать метод macro() для расширения их с помощью наших собственных методов. Для этого нам нужно добавить наши новые пользовательские методы в метод boot() класса AppServiceProvider.Conclusion

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