Введение
Коллекции 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 месяц назад.