laravel-collections

📁 riasvdv/skills 📅 12 days ago
3
总安装量
3
周安装量
#59905
全站排名
安装命令
npx skills add https://github.com/riasvdv/skills --skill laravel-collections

Agent 安装分布

opencode 3
gemini-cli 3
github-copilot 3
codex 3
kimi-cli 3
amp 3

Skill 文档

Laravel Collections

Quick Decision Guide

“Which method do I use?”

Find items:

Need Method
First item matching condition first(fn) or firstWhere('key', 'value')
First item or throw firstOrFail(fn)
Exactly one match or throw sole(fn)
Check value exists contains('value') or contains('key', 'value')
Check key exists has('key')
All items match condition every(fn)

Transform items:

Need Method
Transform each item map(fn)
Transform + flatten one level flatMap(fn)
Extract one field pluck('name')
Extract field, keyed by another pluck('name', 'id')
Select multiple fields select(['id', 'name'])
Change keys mapWithKeys(fn) or keyBy('id')
Map into class instances mapInto(DTO::class)

Filter items:

Need Method
Keep matching items filter(fn)
Remove matching items reject(fn)
Filter by field value where('status', 'active')
Filter by field in list whereIn('status', ['active', 'pending'])
Keep specific keys only only(['id', 'name'])
Remove specific keys except(['password'])
Remove duplicates unique('email')

Group & organize:

Need Method
Group by field groupBy('category')
Group with custom key+value mapToGroups(fn)
Split pass/fail partition(fn)
Key by field (1 item per key) keyBy('id')
Split into chunks chunk(100)

Aggregate:

Need Method
Sum values sum('price')
Average avg('score')
Min/Max min('price') / max('price')
Reduce to single value reduce(fn, $initial)
Count occurrences countBy('type')
Percentage matching percentage(fn)

Combine collections:

Need Method
Merge (overwrites string keys) merge($other)
Append values (re-indexes) concat($other)
Keep only shared values intersect($other)
Get values not in other diff($other)
Pair items by index zip($other)

Mutability Rules

Immutable (return new collection) – almost everything: map, filter, reject, sort, merge, pluck, unique, …

Mutating (modify in place, return $this) – memorize these: transform, push, prepend, put, pull, pop, shift, splice, forget

// WRONG mental model:
$filtered = $collection->push('item'); // $collection IS modified

// Correct approach when you want immutability:
$new = $collection->concat(['item']); // $collection is unchanged

Common Pitfalls

1. each() vs map() vs transform()

// each(): Side-effects, returns ORIGINAL collection
$users->each(fn($u) => $u->notify(new Welcome));

// map(): Transformation, returns NEW collection (original unchanged)
$names = $users->map(fn($u) => $u->name);

// transform(): Transformation, MUTATES original collection
$users->transform(fn($u) => $u->name); // $users is now a collection of names!

2. pluck() key overwrites

When using pluck('name', 'id'), duplicate keys silently overwrite:

collect([
    ['id' => 1, 'name' => 'Alice'],
    ['id' => 1, 'name' => 'Bob'],   // Overwrites Alice
])->pluck('name', 'id');
// [1 => 'Bob']  -- Alice is lost!

Use groupBy if duplicates are expected.

3. filter() without callback removes all falsy values

collect([0, 1, '', 'hello', null, false, []])->filter()->all();
// [1, 'hello'] -- 0, '', null, false, [] are ALL removed

Use whereNotNull() if you only want to remove nulls.

4. N+1 queries with collection iteration

// BAD: N+1 queries
$users->each(fn($user) => $user->posts->count());

// GOOD: Eager load first
$users->load('posts');
$users->each(fn($user) => $user->posts->count());

5. Memory with large datasets

// BAD: Loads all users into memory
User::all()->each(fn($u) => process($u));

// GOOD: Constant memory with cursor
User::cursor()->each(fn($u) => process($u));

// GOOD: Chunked processing
User::chunk(1000, fn($users) => $users->each(fn($u) => process($u)));

6. sort() preserves keys

collect([3, 1, 2])->sort()->all();
// [1 => 1, 2 => 2, 0 => 3] -- keys preserved!

collect([3, 1, 2])->sort()->values()->all();
// [1, 2, 3] -- use values() to re-index

Higher-Order Messages

Proxy pattern for clean, concise collection operations:

// Instead of:
$users->map(function ($user) { return $user->name; });

// Write:
$users->map->name;

// Works with methods too:
$users->each->markAsVip();
$users->sum->votes;
$users->filter->isAdmin();
$users->sortBy->name;
$users->reject->isBlocked();
$users->groupBy->department;

Supported on: average, avg, contains, each, every, filter, first, flatMap, groupBy, keyBy, map, max, min, partition, reject, skipUntil, skipWhile, some, sortBy, sortByDesc, sum, takeUntil, takeWhile, unique.

Extending with Macros

Register custom collection methods (typically in a service provider’s boot method):

use Illuminate\Support\Collection;

Collection::macro('toUpper', function () {
    return $this->map(fn($value) => strtoupper($value));
});

// Usage
collect(['foo', 'bar'])->toUpper(); // ['FOO', 'BAR']

Reference Files