본문으로 건너뛰기
버전: 11.x

컬렉션 (Collections)

소개

Illuminate\Support\Collection 클래스는 데이터 배열을 처리할 때 유연하고 편리한 래퍼를 제공합니다. 아래 예제를 확인해 보세요. collect 헬퍼를 사용해 배열로부터 새로운 컬렉션 인스턴스를 생성한 후, 각 요소에 strtoupper 함수를 적용하고 모든 비어 있는 요소를 제거해 보겠습니다:

$collection = collect(['taylor', 'abigail', null])->map(function (?string $name) {
return strtoupper($name);
})->reject(function (string $name) {
return empty($name);
});

이처럼 Collection 클래스는 메서드 체이닝을 통해 기본 배열에 대해 연속적으로 매핑과 필터링 같은 동작을 부드럽게 수행할 수 있도록 해줍니다. 일반적으로 컬렉션은 불변(immutable) 객체이므로, 각 Collection 메서드는 완전히 새로운 Collection 인스턴스를 반환합니다.

컬렉션 생성하기

위에서 언급한 것처럼, collect 헬퍼는 전달받은 배열로부터 새로운 Illuminate\Support\Collection 인스턴스를 반환합니다. 즉, 컬렉션을 생성하는 방법은 매우 간단합니다:

$collection = collect([1, 2, 3]);

[!NOTE]
Eloquent 쿼리의 결과는 항상 Collection 인스턴스로 반환됩니다.

컬렉션 확장하기

컬렉션은 "매크로(macro) 가능"하므로, 실행 중에 Collection 클래스에 원하는 메서드를 추가할 수 있습니다. Illuminate\Support\Collection 클래스의 macro 메서드는 매크로가 호출될 때 실행될 클로저를 인수로 받습니다. 매크로 클로저에서는 $this를 통해 컬렉션의 다른 메서드에 접근할 수 있으며, 마치 컬렉션 클래스의 진짜 메서드처럼 사용할 수 있습니다. 예를 들어, 아래 코드는 Collection 클래스에 toUpper라는 메서드를 추가합니다:

use Illuminate\Support\Collection;
use Illuminate\Support\Str;

Collection::macro('toUpper', function () {
return $this->map(function (string $value) {
return Str::upper($value);
});
});

$collection = collect(['first', 'second']);

$upper = $collection->toUpper();

// ['FIRST', 'SECOND']

일반적으로, 컬렉션 매크로는 서비스 프로바이더boot 메서드에서 선언하는 것이 좋습니다.

매크로 인수

필요하다면, 추가 인수를 받는 매크로도 정의할 수 있습니다:

use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Lang;

Collection::macro('toLocale', function (string $locale) {
return $this->map(function (string $value) use ($locale) {
return Lang::get($value, [], $locale);
});
});

$collection = collect(['first', 'second']);

$translated = $collection->toLocale('es');

사용 가능한 메서드

남은 컬렉션 문서에서는 Collection 클래스에서 사용할 수 있는 각 메서드에 대해 하나씩 다룹니다. 이 모든 메서드들은 체이닝이 가능하므로, 기본 배열을 연속적으로 다루는 데 매우 유용합니다. 또한 거의 모든 메서드는 새로운 Collection 인스턴스를 반환하므로, 필요하다면 원본 컬렉션을 그대로 보존할 수 있습니다.

메서드 목록

after()

after 메서드는 주어진 값 바로 뒤에 오는 아이템을 반환합니다. 만약 주어진 값이 컬렉션에 없거나 마지막 아이템일 경우 null을 반환합니다:

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

$collection->after(3);

// 4

$collection->after(5);

// null

이 메서드는 "느슨한(loose)" 비교를 이용하여 값을 찾기 때문에, 정수 값을 가진 문자열도 같은 숫자의 정수와 같다고 간주합니다. "엄격한(strict)" 비교를 사용하려면 strict 인수를 추가할 수 있습니다:

collect([2, 4, 6, 8])->after('4', strict: true);

// null

또는, 자신만의 클로저를 전달하여 특정 조건을 만족하는 첫 번째 아이템을 찾을 수도 있습니다:

collect([2, 4, 6, 8])->after(function (int $item, int $key) {
return $item > 5;
});

// 8

all()

all 메서드는 컬렉션이 내부적으로 표현하는 원본 배열을 반환합니다:

collect([1, 2, 3])->all();

// [1, 2, 3]

average()

avg 메서드의 별칭입니다.

avg()

avg 메서드는 특정 키의 평균값을 반환합니다:

$average = collect([
['foo' => 10],
['foo' => 10],
['foo' => 20],
['foo' => 40]
])->avg('foo');

// 20

$average = collect([1, 1, 2, 4])->avg();

// 2

before()

before 메서드는 after 메서드의 반대 동작을 합니다. 주어진 값 바로 앞에 오는 아이템을 반환하며, 주어진 값이 컬렉션에 없거나 첫 번째 아이템일 경우 null을 반환합니다:

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

$collection->before(3);

// 2

$collection->before(1);

// null

collect([2, 4, 6, 8])->before('4', strict: true);

// null

collect([2, 4, 6, 8])->before(function (int $item, int $key) {
return $item > 5;
});

// 4

chunk()

chunk 메서드는 컬렉션을 지정한 크기만큼의 작은 컬렉션으로 나눕니다:

$collection = collect([1, 2, 3, 4, 5, 6, 7]);

$chunks = $collection->chunk(4);

$chunks->all();

// [[1, 2, 3, 4], [5, 6, 7]]

이 메서드는 에서 Bootstrap과 같은 그리드 시스템을 사용할 때 특히 유용합니다. 예를 들어, 그리드로 보여주고 싶은 Eloquent 모델 컬렉션이 있다고 할 때 다음과 같이 활용할 수 있습니다:

@foreach ($products->chunk(3) as $chunk)
<div class="row">
@foreach ($chunk as $product)
<div class="col-xs-4">{{ $product->name }}</div>
@endforeach
</div>
@endforeach

chunkWhile()

chunkWhile 메서드는 전달한 콜백의 평가 결과에 따라 컬렉션을 여러 개의 작은 컬렉션으로 나눕니다. 클로저에 전달되는 $chunk 변수로 이전 요소를 확인할 수 있습니다:

$collection = collect(str_split('AABBCCCD'));

$chunks = $collection->chunkWhile(function (string $value, int $key, Collection $chunk) {
return $value === $chunk->last();
});

$chunks->all();

// [['A', 'A'], ['B', 'B'], ['C', 'C', 'C'], ['D']]

collapse()

collapse 메서드는 여러 배열로 구성된 컬렉션을 하나의 단일 평면(flat) 컬렉션으로 펼쳐줍니다:

$collection = collect([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]);

$collapsed = $collection->collapse();

$collapsed->all();

// [1, 2, 3, 4, 5, 6, 7, 8, 9]

collapseWithKeys()

collapseWithKeys 메서드는 배열 또는 컬렉션으로 이루어진 컬렉션을, 각 원래의 키를 그대로 유지하면서 하나의 컬렉션으로 평탄화합니다:

$collection = collect([
['first' => collect([1, 2, 3])],
['second' => [4, 5, 6]],
['third' => collect([7, 8, 9])]
]);
$collapsed = $collection->collapseWithKeys();

$collapsed->all();

// [
// 'first' => [1, 2, 3],
// 'second' => [4, 5, 6],
// 'third' => [7, 8, 9],
// ]

collect()

collect 메서드는 현재 컬렉션에 담겨 있는 값들로 새로운 Collection 인스턴스를 반환합니다:

$collectionA = collect([1, 2, 3]);

$collectionB = $collectionA->collect();

$collectionB->all();

// [1, 2, 3]

이 메서드는 지연 컬렉션(lazy collections)을 일반적인 Collection 인스턴스로 변환할 때 특히 유용합니다:

$lazyCollection = LazyCollection::make(function () {
yield 1;
yield 2;
yield 3;
});

$collection = $lazyCollection->collect();

$collection::class;

// 'Illuminate\Support\Collection'

$collection->all();

// [1, 2, 3]

[!NOTE]
collect 메서드는 Enumerable 인스턴스를 보통 컬렉션 인스턴스로 전환할 필요가 있을 때 매우 유용합니다. collect()Enumerable 계약의 일부이므로, 언제든 안심하고 Collection 인스턴스를 얻는데 사용할 수 있습니다.

combine()

combine 메서드는 컬렉션의 값들을 키로, 전달한 또 다른 배열 또는 컬렉션의 값들을 값으로 결합합니다:

$collection = collect(['name', 'age']);

$combined = $collection->combine(['George', 29]);

$combined->all();

// ['name' => 'George', 'age' => 29]

concat()

concat 메서드는 주어진 array 또는 컬렉션의 값을 기존 컬렉션의 끝에 덧붙여 추가합니다:

$collection = collect(['John Doe']);

$concatenated = $collection->concat(['Jane Doe'])->concat(['name' => 'Johnny Doe']);

$concatenated->all();

// ['John Doe', 'Jane Doe', 'Johnny Doe']

concat 메서드는 추가된 요소들의 키를 숫자형으로 새로 부여합니다. 연관 배열(associative collection)의 키를 그대로 유지하고 싶다면 merge 메서드를 사용하세요.

contains()

contains 메서드는 컬렉션이 특정 아이템을 포함하는지 여부를 확인합니다. 클로저를 전달해, 주어진 조건을 만족하는 요소가 컬렉션에 존재하는지 확인할 수 있습니다:

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

$collection->contains(function (int $value, int $key) {
return $value > 5;
});

// false

또는, 값을 직접 전달하여 해당 값이 컬렉션에 존재하는지 확인할 수도 있습니다:

$collection = collect(['name' => 'Desk', 'price' => 100]);

$collection->contains('Desk');

// true

$collection->contains('New York');

// false

키/값 쌍을 넘겨, 해당 조합이 존재하는지 검사할 수도 있습니다:

$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 100],
]);

$collection->contains('product', 'Bookcase');

// false

contains 메서드는 값 비교 시 "느슨한(loose)" 비교를 사용합니다. 즉, 숫자의 문자열도 같은 값을 가진 정수와 동일하게 판단합니다. "엄격한(strict)" 비교로 필터링하려면 containsStrict 메서드를 참고하세요.

반대로 컬렉션에 특정 값이 없는지 확인하고 싶을 때는 doesntContain 메서드를 참고하세요.

containsOneItem()

containsOneItem 메서드는 컬렉션에 단 하나의 요소만 존재하는지 확인합니다:

collect([])->containsOneItem();

// false

collect(['1'])->containsOneItem();

// true

collect(['1', '2'])->containsOneItem();

// false

containsStrict()

이 메서드는 contains 메서드와 동일한 시그니처를 가집니다. 그러나 모든 값은 "엄격(strict)" 비교를 통해 비교됩니다.

[!NOTE]
이 메서드는 Eloquent 컬렉션을 사용할 때 동작이 달라집니다.

count()

count 메서드는 컬렉션의 전체 항목 개수를 반환합니다.

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

$collection->count();

// 4

countBy()

countBy 메서드는 컬렉션 내 값들의 등장 횟수를 셉니다. 기본적으로 컬렉션의 각 요소가 몇 번씩 등장하는지 세어주므로, 특정 "유형"의 항목이 몇 개인지 파악할 수 있습니다.

$collection = collect([1, 2, 2, 2, 3]);

$counted = $collection->countBy();

$counted->all();

// [1 => 1, 2 => 3, 3 => 1]

countBy 메서드에 클로저를 전달하여, 사용자 정의 값으로 각 항목의 개수를 셀 수도 있습니다.

$collection = collect(['[email protected]', '[email protected]', '[email protected]']);

$counted = $collection->countBy(function (string $email) {
return substr(strrchr($email, "@"), 1);
});

$counted->all();

// ['gmail.com' => 2, 'yahoo.com' => 1]

crossJoin()

crossJoin 메서드는 컬렉션의 값들을 주어진 배열이나 컬렉션과 크로스 조인하여, 가능한 모든 조합(카티션 곱, Cartesian product)을 반환합니다.

$collection = collect([1, 2]);

$matrix = $collection->crossJoin(['a', 'b']);

$matrix->all();

/*
[
[1, 'a'],
[1, 'b'],
[2, 'a'],
[2, 'b'],
]
*/

$collection = collect([1, 2]);

$matrix = $collection->crossJoin(['a', 'b'], ['I', 'II']);

$matrix->all();

/*
[
[1, 'a', 'I'],
[1, 'a', 'II'],
[1, 'b', 'I'],
[1, 'b', 'II'],
[2, 'a', 'I'],
[2, 'a', 'II'],
[2, 'b', 'I'],
[2, 'b', 'II'],
]
*/

dd()

dd 메서드는 컬렉션의 항목을 출력(dump)한 뒤 스크립트 실행을 중단합니다.

$collection = collect(['John Doe', 'Jane Doe']);

$collection->dd();

/*
Collection {
#items: array:2 [
0 => "John Doe"
1 => "Jane Doe"
]
}
*/

스크립트 실행을 중단하지 않고 컬렉션을 출력만 하려면 dump 메서드를 사용하십시오.

diff()

diff 메서드는 컬렉션과 다른 컬렉션 또는 일반 PHP array를 값 기준으로 비교합니다. 이 메서드는 기준 컬렉션에 존재하지 않는 원래 컬렉션의 값을 반환합니다.

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

$diff = $collection->diff([2, 4, 6, 8]);

$diff->all();

// [1, 3, 5]

[!NOTE]
이 메서드는 Eloquent 컬렉션을 사용할 때 동작이 달라집니다.

diffAssoc()

diffAssoc 메서드는 컬렉션과 다른 컬렉션 또는 일반 PHP array를 '키와 값' 기준으로 비교합니다. 이때, 기준 컬렉션에 존재하지 않는 원래 컬렉션의 키/값 쌍을 반환합니다.

$collection = collect([
'color' => 'orange',
'type' => 'fruit',
'remain' => 6,
]);

$diff = $collection->diffAssoc([
'color' => 'yellow',
'type' => 'fruit',
'remain' => 3,
'used' => 6,
]);

$diff->all();

// ['color' => 'orange', 'remain' => 6]

diffAssocUsing()

diffAssoc와 달리, diffAssocUsing 메서드는 인덱스(키) 비교에 직접 지정한 콜백 함수를 사용합니다.

$collection = collect([
'color' => 'orange',
'type' => 'fruit',
'remain' => 6,
]);

$diff = $collection->diffAssocUsing([
'Color' => 'yellow',
'Type' => 'fruit',
'Remain' => 3,
], 'strnatcasecmp');

$diff->all();

// ['color' => 'orange', 'remain' => 6]

콜백 함수는, 비교 대상이 기준보다 작으면 0보다 작은 정수, 기준과 같으면 0, 크면 0보다 큰 정수를 반환하는 함수여야 합니다. 자세한 정보는 PHP의 array_diff_uassoc 설명서를 참고해 주세요. 이 메서드는 내부적으로 해당 PHP 함수를 사용합니다.

diffKeys()

diffKeys 메서드는 컬렉션과 다른 컬렉션 또는 일반 PHP array를 키 기준으로 비교합니다. 이때, 기준 컬렉션에 존재하지 않는 원래 컬렉션의 키/값 쌍을 반환합니다.

$collection = collect([
'one' => 10,
'two' => 20,
'three' => 30,
'four' => 40,
'five' => 50,
]);

$diff = $collection->diffKeys([
'two' => 2,
'four' => 4,
'six' => 6,
'eight' => 8,
]);

$diff->all();

// ['one' => 10, 'three' => 30, 'five' => 50]

doesntContain()

doesntContain 메서드는 컬렉션에 특정 값이 없는지 검사합니다. 클로저를 전달하면, 해당 조건을 만족하는 요소가 컬렉션에 '존재하지 않는지' 확인할 수 있습니다.

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

$collection->doesntContain(function (int $value, int $key) {
return $value < 5;
});

// false

또한, 문자열을 직접 전달하여 해당 값이 컬렉션에 없는지 확인할 수 있습니다.

$collection = collect(['name' => 'Desk', 'price' => 100]);

$collection->doesntContain('Table');

// true

$collection->doesntContain('Desk');

// false

키/값 쌍을 전달하여, 해당 키/값 쌍이 컬렉션에 없는지 검사할 수도 있습니다.

$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 100],
]);

$collection->doesntContain('product', 'Bookcase');

// true

doesntContain 메서드는 값 비교 시 "느슨한(loose)" 비교를 사용합니다. 즉, 정수로 변환 가능한 문자열은 같은 정수로 간주하여 일치하는 것으로 처리합니다.

dot()

dot 메서드는 다차원 컬렉션을 단일 단계의 컬렉션으로 평탄화하며, 깊이(depth)를 "닷(dot) 표기법"으로 표시합니다.

$collection = collect(['products' => ['desk' => ['price' => 100]]]);

$flattened = $collection->dot();

$flattened->all();

// ['products.desk.price' => 100]

dump()

dump 메서드는 컬렉션의 항목을 출력(dump)합니다.

$collection = collect(['John Doe', 'Jane Doe']);

$collection->dump();

/*
Collection {
#items: array:2 [
0 => "John Doe"
1 => "Jane Doe"
]
}
*/

컬렉션을 출력한 후 스크립트 실행을 중단하고 싶다면 dd 메서드를 사용하세요.

duplicates()

duplicates 메서드는 컬렉션 내에서 중복된 값을 찾아 반환합니다.

$collection = collect(['a', 'b', 'a', 'c', 'b']);

$collection->duplicates();

// [2 => 'a', 4 => 'b']

컬렉션에 배열이나 객체가 포함되어 있을 경우, 중복 여부를 확인할 속성의 키를 지정하여 사용할 수 있습니다.

$employees = collect([
['email' => '[email protected]', 'position' => 'Developer'],
['email' => '[email protected]', 'position' => 'Designer'],
['email' => '[email protected]', 'position' => 'Developer'],
]);

$employees->duplicates('position');

// [2 => 'Developer']

duplicatesStrict()

이 메서드는 duplicates 메서드와 동일한 시그니처를 가집니다. 그러나 모든 값은 "엄격(strict)" 비교를 통해 중복 여부를 판단합니다.

each()

each 메서드는 컬렉션의 항목을 순회하며, 각 항목을 클로저에 전달합니다.

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

$collection->each(function (int $item, int $key) {
// ...
});

순회를 중단하고 싶을 때는, 클로저에서 false를 반환하면 해당 지점에서 순회가 멈춥니다.

$collection->each(function (int $item, int $key) {
if (/* condition */) {
return false;
}
});

eachSpread()

eachSpread 메서드는 컬렉션의 항목(배열 형태)을 펼쳐서(closing unpacking) 각각의 값들을 콜백에 전달하며 순회합니다.

$collection = collect([['John Doe', 35], ['Jane Doe', 33]]);

$collection->eachSpread(function (string $name, int $age) {
// ...
});

이 역시 콜백에서 false를 반환하면 순회가 중단됩니다.

$collection->eachSpread(function (string $name, int $age) {
return false;
});

ensure()

ensure 메서드는 컬렉션의 모든 요소가 지정한 타입 또는 타입 목록에 해당하는지 검사합니다. 그렇지 않을 경우 UnexpectedValueException 예외가 발생합니다.

return $collection->ensure(User::class);

return $collection->ensure([User::class, Customer::class]);

기본 타입인 string, int, float, bool, array 등도 지정할 수 있습니다.

return $collection->ensure('int');

[!WARNING]
ensure 메서드는 나중에 컬렉션에 다른 타입의 요소가 추가되는 것을 방지해주지는 않습니다.

every()

every 메서드는 컬렉션의 모든 요소가 주어진 조건을 만족하는지 검사할 때 사용합니다.

collect([1, 2, 3, 4])->every(function (int $value, int $key) {
return $value > 2;
});

// false

컬렉션이 비어 있는 경우 every 메서드는 true를 반환합니다.

$collection = collect([]);

$collection->every(function (int $value, int $key) {
return $value > 2;
});

// true

except()

except 메서드는 지정한 키를 가진 항목을 제외한 컬렉션의 모든 항목을 반환합니다.

$collection = collect(['product_id' => 1, 'price' => 100, 'discount' => false]);

$filtered = $collection->except(['price', 'discount']);

$filtered->all();

// ['product_id' => 1]

반대로 동작하는 메서드는 only입니다.

[!NOTE]
이 메서드는 Eloquent 컬렉션을 사용할 때 동작이 달라집니다.

filter()

filter 메서드는 주어진 콜백 함수를 통해 컬렉션의 항목을 필터링하여, 조건을 만족하는 항목만 남깁니다.

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

$filtered = $collection->filter(function (int $value, int $key) {
return $value > 2;
});

$filtered->all();

// [3, 4]

콜백을 지정하지 않으면, 컬렉션에서 false로 평가되는 모든 값이 제거됩니다.

$collection = collect([1, 2, 3, null, false, '', 0, []]);

$collection->filter()->all();

// [1, 2, 3]

반대 동작을 하는 메서드는 reject입니다.

first()

first 메서드는 컬렉션의 각 항목 중 지정한 조건을 만족하는 첫 번째 항목을 반환합니다.

collect([1, 2, 3, 4])->first(function (int $value, int $key) {
return $value > 2;
});

// 3

인수를 전달하지 않으면, 컬렉션의 첫 번째 항목을 반환합니다. 컬렉션이 비어 있으면 null을 반환합니다.

collect([1, 2, 3, 4])->first();

// 1

firstOrFail()

firstOrFail 메서드는 first 메서드와 사용법이 동일하나, 조건을 만족하는 결과가 없을 경우 Illuminate\Support\ItemNotFoundException 예외가 발생합니다.

collect([1, 2, 3, 4])->firstOrFail(function (int $value, int $key) {
return $value > 5;
});

// Throws ItemNotFoundException...

인수를 전달하지 않을 경우, 컬렉션의 첫 번째 항목을 반환합니다. 컬렉션이 비어 있으면 Illuminate\Support\ItemNotFoundException 예외가 발생합니다.

collect([])->firstOrFail();

// Throws ItemNotFoundException...

firstWhere()

firstWhere 메서드는 지정한 키/값 쌍과 일치하는 컬렉션 내 첫 번째 항목을 반환합니다.

$collection = collect([
['name' => 'Regena', 'age' => null],
['name' => 'Linda', 'age' => 14],
['name' => 'Diego', 'age' => 23],
['name' => 'Linda', 'age' => 84],
]);

$collection->firstWhere('name', 'Linda');

// ['name' => 'Linda', 'age' => 14]

비교 연산자를 사용할 수도 있습니다.

$collection->firstWhere('age', '>=', 18);

// ['name' => 'Diego', 'age' => 23]

where 메서드처럼 인수 하나만 전달하면, 해당 키가 'truthy' 값(즉, 참으로 평가되는 값)을 가진 첫 번째 항목을 반환합니다.

$collection->firstWhere('age');

// ['name' => 'Linda', 'age' => 14]

flatMap()

flatMap 메서드는 컬렉션의 각 값을 주어진 클로저에 전달하여 변형하고, 변형된 결과로 새로운 컬렉션을 만듭니다. 그 후에, 반환된 배열이 한 단계 평탄화됩니다.

$collection = collect([
['name' => 'Sally'],
['school' => 'Arkansas'],
['age' => 28]
]);

$flattened = $collection->flatMap(function (array $values) {
return array_map('strtoupper', $values);
});

$flattened->all();

// ['name' => 'SALLY', 'school' => 'ARKANSAS', 'age' => '28'];

flatten()

flatten 메서드는 다차원 컬렉션을 한 단계의 단일 컬렉션으로 평탄화합니다.

$collection = collect([
'name' => 'taylor',
'languages' => [
'php', 'javascript'
]
]);

$flattened = $collection->flatten();

$flattened->all();

// ['taylor', 'php', 'javascript'];

필요하다면 flatten 메서드에 "깊이(depth)" 인수를 전달할 수도 있습니다.

$collection = collect([
'Apple' => [
[
'name' => 'iPhone 6S',
'brand' => 'Apple'
],
],
'Samsung' => [
[
'name' => 'Galaxy S7',
'brand' => 'Samsung'
],
],
]);

$products = $collection->flatten(1);

$products->values()->all();

/*
[
['name' => 'iPhone 6S', 'brand' => 'Apple'],
['name' => 'Galaxy S7', 'brand' => 'Samsung'],
]
*/

이 예시에서, 깊이 인수를 생략하고 flatten을 호출하면 중첩 배열까지 모두 평탄화되어 ['iPhone 6S', 'Apple', 'Galaxy S7', 'Samsung']가 됩니다. 깊이를 지정하면 몇 단계까지 평탄화할지 직접 선택할 수 있습니다.

flip()

flip 메서드는 컬렉션의 키와 값을 서로 뒤바꿉니다.

$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);

$flipped = $collection->flip();

$flipped->all();

// ['taylor' => 'name', 'laravel' => 'framework']

forget()

forget 메서드는 컬렉션에서 지정한 키에 해당하는 아이템을 제거합니다.

$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);

// 하나의 키를 제거...
$collection->forget('name');

// ['framework' => 'laravel']

// 여러 키를 제거...
$collection->forget(['name', 'framework']);

// []

[!WARNING]
대부분의 다른 컬렉션 메서드와 달리, forget은 새로운 컬렉션을 반환하지 않고, 호출된 컬렉션 자체를 수정합니다.

forPage()

forPage 메서드는 지정한 페이지 번호에 해당하는 아이템만 포함하는 새로운 컬렉션을 반환합니다. 첫 번째 인수로 페이지 번호를, 두 번째 인수로 한 페이지에 보여줄 아이템 개수를 전달할 수 있습니다.

$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]);

$chunk = $collection->forPage(2, 3);

$chunk->all();

// [4, 5, 6]

get()

get 메서드는 지정한 키에 해당하는 아이템을 반환합니다. 키가 존재하지 않으면 null을 반환합니다.

$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);

$value = $collection->get('name');

// taylor

두 번째 인수로 기본값을 전달할 수도 있습니다.

$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);

$value = $collection->get('age', 34);

// 34

기본값으로 콜백을 전달할 수도 있습니다. 만약 지정한 키가 존재하지 않으면, 해당 콜백의 결과가 반환됩니다.

$collection->get('email', function () {
return '[email protected]';
});

// [email protected]

groupBy()

groupBy 메서드는 컬렉션의 아이템을 지정한 키로 그룹화합니다.

$collection = collect([
['account_id' => 'account-x10', 'product' => 'Chair'],
['account_id' => 'account-x10', 'product' => 'Bookcase'],
['account_id' => 'account-x11', 'product' => 'Desk'],
]);

$grouped = $collection->groupBy('account_id');

$grouped->all();

/*
[
'account-x10' => [
['account_id' => 'account-x10', 'product' => 'Chair'],
['account_id' => 'account-x10', 'product' => 'Bookcase'],
],
'account-x11' => [
['account_id' => 'account-x11', 'product' => 'Desk'],
],
]
*/

문자열 키 대신 콜백을 전달할 수도 있습니다. 콜백은 그룹의 키로 사용할 값을 반환해야 합니다.

$grouped = $collection->groupBy(function (array $item, int $key) {
return substr($item['account_id'], -3);
});

$grouped->all();

/*
[
'x10' => [
['account_id' => 'account-x10', 'product' => 'Chair'],
['account_id' => 'account-x10', 'product' => 'Bookcase'],
],
'x11' => [
['account_id' => 'account-x11', 'product' => 'Desk'],
],
]
*/

여러 개의 그룹화 기준을 배열로 전달할 수도 있습니다. 배열의 각 요소는 다차원 배열의 각 단계에 적용됩니다.

$data = new Collection([
10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']],
20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']],
30 => ['user' => 3, 'skill' => 2, 'roles' => ['Role_1']],
40 => ['user' => 4, 'skill' => 2, 'roles' => ['Role_2']],
]);

$result = $data->groupBy(['skill', function (array $item) {
return $item['roles'];
}], preserveKeys: true);

/*
[
1 => [
'Role_1' => [
10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']],
20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']],
],
'Role_2' => [
20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']],
],
'Role_3' => [
10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']],
],
],
2 => [
'Role_1' => [
30 => ['user' => 3, 'skill' => 2, 'roles' => ['Role_1']],
],
'Role_2' => [
40 => ['user' => 4, 'skill' => 2, 'roles' => ['Role_2']],
],
],
];
*/

has()

has 메서드는 컬렉션에 지정한 키가 존재하는지 여부를 확인합니다.

$collection = collect(['account_id' => 1, 'product' => 'Desk', 'amount' => 5]);

$collection->has('product');

// true

$collection->has(['product', 'amount']);

// true

$collection->has(['amount', 'price']);

// false

hasAny()

hasAny 메서드는 전달한 키들 중 하나라도 컬렉션에 존재하는지 확인합니다.

$collection = collect(['account_id' => 1, 'product' => 'Desk', 'amount' => 5]);

$collection->hasAny(['product', 'price']);

// true

$collection->hasAny(['name', 'price']);

// false

implode()

implode 메서드는 컬렉션의 아이템을 연결하여 하나의 문자열로 만듭니다. 컬렉션이 배열이나 객체를 포함하는 경우, 연결할 속성의 키와 각 값을 이어붙일 구분자(Glue)를 인수로 전달해야 합니다.

$collection = collect([
['account_id' => 1, 'product' => 'Desk'],
['account_id' => 2, 'product' => 'Chair'],
]);

$collection->implode('product', ', ');

// Desk, Chair

컬렉션이 단순 문자열이나 숫자 값만 포함한다면, 구분자만 인수로 전달하면 됩니다.

collect([1, 2, 3, 4, 5])->implode('-');

// '1-2-3-4-5'

implode 메서드에 클로저를 전달해 각 값을 원하는 방식으로 가공한 뒤 연결할 수도 있습니다.

$collection->implode(function (array $item, int $key) {
return strtoupper($item['product']);
}, ', ');

// DESK, CHAIR

intersect()

intersect 메서드는 원본 컬렉션에 존재하지 않는 값을 모두 제거합니다. 즉, 주어진 array 또는 컬렉션에 포함된 값만 남게 됩니다. 결과 컬렉션은 원본 컬렉션의 키를 그대로 유지합니다.

$collection = collect(['Desk', 'Sofa', 'Chair']);

$intersect = $collection->intersect(['Desk', 'Chair', 'Bookcase']);

$intersect->all();

// [0 => 'Desk', 2 => 'Chair']

[!NOTE]
이 메서드는 Eloquent 컬렉션을 사용할 때 동작이 다를 수 있습니다.

intersectUsing()

intersectUsing 메서드는 주어진 array 또는 컬렉션에 포함되어 있지 않은 값들을 제거하지만, 값 비교 시 사용자가 정의한 콜백을 사용합니다. 결과 컬렉션은 원본 컬렉션의 키를 그대로 유지합니다.

$collection = collect(['Desk', 'Sofa', 'Chair']);

$intersect = $collection->intersectUsing(['desk', 'chair', 'bookcase'], function ($a, $b) {
return strcasecmp($a, $b);
});

$intersect->all();

// [0 => 'Desk', 2 => 'Chair']

intersectAssoc()

intersectAssoc 메서드는 원본 컬렉션과 비교 대상 컬렉션 또는 array 모두에 존재하는 키/값 쌍만 반환합니다.

$collection = collect([
'color' => 'red',
'size' => 'M',
'material' => 'cotton'
]);

$intersect = $collection->intersectAssoc([
'color' => 'blue',
'size' => 'M',
'material' => 'polyester'
]);

$intersect->all();

// ['size' => 'M']

intersectAssocUsing()

intersectAssocUsing 메서드는 원본 컬렉션과 비교 대상 컬렉션 또는 array 모두에 존재하는 키/값 쌍만 반환하되, 각 키와 값의 비교에 사용자 정의 콜백을 사용합니다.

$collection = collect([
'color' => 'red',
'Size' => 'M',
'material' => 'cotton',
]);

$intersect = $collection->intersectAssocUsing([
'color' => 'blue',
'size' => 'M',
'material' => 'polyester',
], function ($a, $b) {
return strcasecmp($a, $b);
});

$intersect->all();

// ['Size' => 'M']

intersectByKeys()

intersectByKeys 메서드는 주어진 array 또는 컬렉션에 존재하지 않는 키와 그에 대응하는 값을 모두 제거합니다.

$collection = collect([
'serial' => 'UX301', 'type' => 'screen', 'year' => 2009,
]);

$intersect = $collection->intersectByKeys([
'reference' => 'UX404', 'type' => 'tab', 'year' => 2011,
]);

$intersect->all();

// ['type' => 'screen', 'year' => 2009]

isEmpty()

isEmpty 메서드는 컬렉션이 비어 있으면 true, 그렇지 않으면 false를 반환합니다.

collect([])->isEmpty();

// true

isNotEmpty()

isNotEmpty 메서드는 컬렉션이 비어 있지 않으면 true, 비어 있으면 false를 반환합니다.

collect([])->isNotEmpty();

// false

join()

join 메서드는 컬렉션의 값을 특정 문자열로 연결합니다. 두 번째 인수를 사용하면 마지막 요소를 어떻게 붙일지 지정할 수 있습니다.

collect(['a', 'b', 'c'])->join(', '); // 'a, b, c'
collect(['a', 'b', 'c'])->join(', ', ', and '); // 'a, b, and c'
collect(['a', 'b'])->join(', ', ' and '); // 'a and b'
collect(['a'])->join(', ', ' and '); // 'a'
collect([])->join(', ', ' and '); // ''

keyBy()

keyBy 메서드는 지정한 키를 기준으로 컬렉션의 키를 재설정합니다. 동일한 키가 여러 번 등장하면, 마지막 항목만 남게 됩니다.

$collection = collect([
['product_id' => 'prod-100', 'name' => 'Desk'],
['product_id' => 'prod-200', 'name' => 'Chair'],
]);

$keyed = $collection->keyBy('product_id');

$keyed->all();

/*
[
'prod-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
]
*/

메서드에 콜백을 전달할 수도 있습니다. 콜백은 컬렉션의 키로 사용할 값을 반환해야 합니다.

$keyed = $collection->keyBy(function (array $item, int $key) {
return strtoupper($item['product_id']);
});

$keyed->all();

/*
[
'PROD-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
'PROD-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
]
*/

keys()

keys 메서드는 컬렉션에 있는 모든 키를 반환합니다.

$collection = collect([
'prod-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
]);

$keys = $collection->keys();

$keys->all();

// ['prod-100', 'prod-200']

last()

last 메서드는 지정한 조건을 만족하는 컬렉션의 마지막 요소를 반환합니다.

collect([1, 2, 3, 4])->last(function (int $value, int $key) {
return $value < 3;
});

// 2

아무 인수도 지정하지 않으면, 컬렉션의 마지막 요소를 반환합니다. 컬렉션이 비어 있으면 null을 반환합니다.

collect([1, 2, 3, 4])->last();

// 4

lazy()

lazy 메서드는 현재 컬렉션의 아이템들을 기반으로 새로운 LazyCollection 인스턴스를 생성합니다.

$lazyCollection = collect([1, 2, 3, 4])->lazy();

$lazyCollection::class;

// Illuminate\Support\LazyCollection

$lazyCollection->all();

// [1, 2, 3, 4]

이 기능은 많은 수의 아이템을 가진 거대한 Collection에서 변환을 수행해야 할 때 특히 유용합니다.

$count = $hugeCollection
->lazy()
->where('country', 'FR')
->where('balance', '>', '100')
->count();

컬렉션을 LazyCollection으로 변환하면, 추가적인 메모리 할당 없이 결과를 필터링할 수 있습니다. 원본 컬렉션은 내부적으로 여전히 모든 값을 메모리에 보관하지만, 이후의 필터 동작에서는 추가 메모리를 필요로 하지 않습니다. 즉, 필터링 이후 결과에 대해선 사실상 추가 메모리 사용이 거의 없습니다.

macro()

정적 macro 메서드를 사용하면 실행 시간에 Collection 클래스에 메서드를 추가할 수 있습니다. 자세한 내용은 컬렉션 확장하기 관련 문서를 참고하세요.

make()

정적 make 메서드는 새로운 컬렉션 인스턴스를 생성합니다. 자세한 내용은 컬렉션 생성 항목을 참고하세요.

map()

map 메서드는 컬렉션을 순회하며 각 값을 지정한 콜백에 전달합니다. 콜백에서 아이템을 가공하고 반환하면, 변형된 값들로 새로운 컬렉션을 생성합니다.

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

$multiplied = $collection->map(function (int $item, int $key) {
return $item * 2;
});

$multiplied->all();

// [2, 4, 6, 8, 10]

[!WARNING]
대부분의 컬렉션 메서드처럼, map은 새로운 컬렉션 인스턴스를 반환하며, 원본 컬렉션은 수정하지 않습니다. 원본 컬렉션 자체를 변형하려면 transform 메서드를 사용하세요.

mapInto()

mapInto() 메서드는 컬렉션을 순회하면서, 각 값을 생성자의 인수로 전달하여 지정한 클래스의 새 인스턴스를 생성합니다.

class Currency
{
/**
* Create a new currency instance.
*/
function __construct(
public string $code,
) {}
}

$collection = collect(['USD', 'EUR', 'GBP']);

$currencies = $collection->mapInto(Currency::class);

$currencies->all();

// [Currency('USD'), Currency('EUR'), Currency('GBP')]

mapSpread()

mapSpread 메서드는 컬렉션의 아이템(중첩된 값들)을 콜백에 분리해서 전달합니다. 콜백에서 가공된 값들을 반환하면, 변형된 값들로 새로운 컬렉션을 만듭니다.

$collection = collect([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);

$chunks = $collection->chunk(2);

$sequence = $chunks->mapSpread(function (int $even, int $odd) {
return $even + $odd;
});

$sequence->all();

// [1, 5, 9, 13, 17]

mapToGroups()

mapToGroups 메서드는 컬렉션의 항목들을 주어진 클로저에 따라 그룹으로 묶습니다. 이 클로저는 하나의 키/값 쌍만을 포함하는 연관 배열을 반환해야 하며, 이로써 새로운 그룹별 값의 컬렉션을 형성하게 됩니다:

$collection = collect([
[
'name' => 'John Doe',
'department' => 'Sales',
],
[
'name' => 'Jane Doe',
'department' => 'Sales',
],
[
'name' => 'Johnny Doe',
'department' => 'Marketing',
]
]);

$grouped = $collection->mapToGroups(function (array $item, int $key) {
return [$item['department'] => $item['name']];
});

$grouped->all();

/*
[
'Sales' => ['John Doe', 'Jane Doe'],
'Marketing' => ['Johnny Doe'],
]
*/

$grouped->get('Sales')->all();

// ['John Doe', 'Jane Doe']

mapWithKeys()

mapWithKeys 메서드는 컬렉션을 순회하면서 각 값에 대해 주어진 콜백을 호출합니다. 이 콜백은 하나의 키/값 쌍만을 포함하는 연관 배열을 반환해야 합니다:

$collection = collect([
[
'name' => 'John',
'department' => 'Sales',
'email' => '[email protected]',
],
[
'name' => 'Jane',
'department' => 'Marketing',
'email' => '[email protected]',
]
]);

$keyed = $collection->mapWithKeys(function (array $item, int $key) {
return [$item['email'] => $item['name']];
});

$keyed->all();

/*
[
'[email protected]' => 'John',
'[email protected]' => 'Jane',
]
*/

max()

max 메서드는 지정한 키의 최댓값을 반환합니다:

$max = collect([
['foo' => 10],
['foo' => 20]
])->max('foo');

// 20

$max = collect([1, 2, 3, 4, 5])->max();

// 5

median()

median 메서드는 지정한 키의 중앙값(중앙값)을 반환합니다:

$median = collect([
['foo' => 10],
['foo' => 10],
['foo' => 20],
['foo' => 40]
])->median('foo');

// 15

$median = collect([1, 1, 2, 4])->median();

// 1.5

merge()

merge 메서드는 주어진 배열이나 컬렉션을 원본 컬렉션과 병합합니다. 만약 주어진 항목의 문자열 키가 원본 컬렉션의 문자열 키와 일치하는 경우, 주어진 항목의 값이 원본 컬렉션의 값을 덮어씁니다:

$collection = collect(['product_id' => 1, 'price' => 100]);

$merged = $collection->merge(['price' => 200, 'discount' => false]);

$merged->all();

// ['product_id' => 1, 'price' => 200, 'discount' => false]

주어진 항목의 키가 숫자인 경우, 값이 컬렉션 끝에 추가됩니다:

$collection = collect(['Desk', 'Chair']);

$merged = $collection->merge(['Bookcase', 'Door']);

$merged->all();

// ['Desk', 'Chair', 'Bookcase', 'Door']

mergeRecursive()

mergeRecursive 메서드는 주어진 배열이나 컬렉션을 원본 컬렉션과 재귀적으로 병합합니다. 만약 주어진 항목의 문자열 키가 원본 컬렉션의 문자열 키와 일치하는 경우, 이 키의 값들이 배열로 병합되며, 이 동작은 재귀적으로 적용됩니다:

$collection = collect(['product_id' => 1, 'price' => 100]);

$merged = $collection->mergeRecursive([
'product_id' => 2,
'price' => 200,
'discount' => false
]);

$merged->all();

// ['product_id' => [1, 2], 'price' => [100, 200], 'discount' => false]

min()

min 메서드는 지정한 키의 최솟값을 반환합니다:

$min = collect([['foo' => 10], ['foo' => 20]])->min('foo');

// 10

$min = collect([1, 2, 3, 4, 5])->min();

// 1

mode()

mode 메서드는 지정한 키의 최빈값(가장 많이 등장한 값)을 반환합니다:

$mode = collect([
['foo' => 10],
['foo' => 10],
['foo' => 20],
['foo' => 40]
])->mode('foo');

// [10]

$mode = collect([1, 1, 2, 4])->mode();

// [1]

$mode = collect([1, 1, 2, 2])->mode();

// [1, 2]

multiply()

multiply 메서드는 컬렉션의 모든 항목을 지정한 횟수만큼 반복하여 복제한 새 컬렉션을 만듭니다:

$users = collect([
['name' => 'User #1', 'email' => '[email protected]'],
['name' => 'User #2', 'email' => '[email protected]'],
])->multiply(3);

/*
[
['name' => 'User #1', 'email' => '[email protected]'],
['name' => 'User #2', 'email' => '[email protected]'],
['name' => 'User #1', 'email' => '[email protected]'],
['name' => 'User #2', 'email' => '[email protected]'],
['name' => 'User #1', 'email' => '[email protected]'],
['name' => 'User #2', 'email' => '[email protected]'],
]
*/

nth()

nth 메서드는 컬렉션에서 n번째마다 한 번씩 요소를 선택하여 새로운 컬렉션을 생성합니다:

$collection = collect(['a', 'b', 'c', 'd', 'e', 'f']);

$collection->nth(4);

// ['a', 'e']

두 번째 인수로 시작 위치(오프셋)를 지정할 수도 있습니다:

$collection->nth(4, 1);

// ['b', 'f']

only()

only 메서드는 컬렉션에서 지정한 키들만 가진 항목들만 반환합니다:

$collection = collect([
'product_id' => 1,
'name' => 'Desk',
'price' => 100,
'discount' => false
]);

$filtered = $collection->only(['product_id', 'name']);

$filtered->all();

// ['product_id' => 1, 'name' => 'Desk']

only의 반대 동작이 필요한 경우 except 메서드를 참고하세요.

[!NOTE]
Eloquent 컬렉션을 사용할 때는 이 메서드의 동작이 다르게 동작합니다.

pad()

pad 메서드는 배열의 길이가 지정된 크기에 도달할 때까지 주어진 값으로 배열을 채웁니다. 이 메서드는 PHP의 array_pad 함수와 유사하게 동작합니다.

배열을 왼쪽(시작 부분)으로 패딩하려면, 크기를 음수로 지정해야 합니다. 만약 배열의 길이가 지정된 크기보다 크거나 같으면 패딩이 적용되지 않습니다:

$collection = collect(['A', 'B', 'C']);

$filtered = $collection->pad(5, 0);

$filtered->all();

// ['A', 'B', 'C', 0, 0]

$filtered = $collection->pad(-5, 0);

$filtered->all();

// [0, 0, 'A', 'B', 'C']

partition()

partition 메서드는 PHP 배열 구조 분해 할당과 결합하여, 특정 조건을 통과하는 요소와 통과하지 못하는 요소를 분리할 수 있습니다:

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

[$underThree, $equalOrAboveThree] = $collection->partition(function (int $i) {
return $i < 3;
});

$underThree->all();

// [1, 2]

$equalOrAboveThree->all();

// [3, 4, 5, 6]

percentage()

percentage 메서드는 컬렉션에서 특정 조건을 통과하는 항목의 비율(%)을 빠르게 계산할 때 사용할 수 있습니다:

$collection = collect([1, 1, 2, 2, 2, 3]);

$percentage = $collection->percentage(fn ($value) => $value === 1);

// 33.33

기본적으로 결과는 소수점 둘째 자리까지 반올림됩니다. 하지만 두 번째 인자(precision)를 이용해 자릿수를 커스터마이즈할 수도 있습니다:

$percentage = $collection->percentage(fn ($value) => $value === 1, precision: 3);

// 33.333

pipe()

pipe 메서드는 컬렉션을 주어진 클로저로 전달하고, 그 실행 결과를 반환합니다:

$collection = collect([1, 2, 3]);

$piped = $collection->pipe(function (Collection $collection) {
return $collection->sum();
});

// 6

pipeInto()

pipeInto 메서드는 지정한 클래스의 새로운 인스턴스를 생성하고, 컬렉션을 해당 클래스의 생성자에 전달합니다:

class ResourceCollection
{
/**
* Create a new ResourceCollection instance.
*/
public function __construct(
public Collection $collection,
) {}
}

$collection = collect([1, 2, 3]);

$resource = $collection->pipeInto(ResourceCollection::class);

$resource->collection->all();

// [1, 2, 3]

pipeThrough()

pipeThrough 메서드는 컬렉션을 주어진 클로저 배열에 차례대로 전달하고, 그 최종 결과를 반환합니다:

use Illuminate\Support\Collection;

$collection = collect([1, 2, 3]);

$result = $collection->pipeThrough([
function (Collection $collection) {
return $collection->merge([4, 5]);
},
function (Collection $collection) {
return $collection->sum();
},
]);

// 15

pluck()

pluck 메서드는 지정한 키에 해당하는 모든 값을 추출해 반환합니다:

$collection = collect([
['product_id' => 'prod-100', 'name' => 'Desk'],
['product_id' => 'prod-200', 'name' => 'Chair'],
]);

$plucked = $collection->pluck('name');

$plucked->all();

// ['Desk', 'Chair']

결과 컬렉션의 키를 어떻게 지정할지 추가적으로 설정할 수도 있습니다:

$plucked = $collection->pluck('name', 'product_id');

$plucked->all();

// ['prod-100' => 'Desk', 'prod-200' => 'Chair']

pluck 메서드는 "점 표기법(dot notation)"을 사용하여 중첩된 값을 추출하는 것도 지원합니다:

$collection = collect([
[
'name' => 'Laracon',
'speakers' => [
'first_day' => ['Rosa', 'Judith'],
],
],
[
'name' => 'VueConf',
'speakers' => [
'first_day' => ['Abigail', 'Joey'],
],
],
]);

$plucked = $collection->pluck('speakers.first_day');

$plucked->all();

// [['Rosa', 'Judith'], ['Abigail', 'Joey']]

키가 중복되는 경우, 마지막에 일치했던 값이 pluck 결과 컬렉션에 저장됩니다:

$collection = collect([
['brand' => 'Tesla', 'color' => 'red'],
['brand' => 'Pagani', 'color' => 'white'],
['brand' => 'Tesla', 'color' => 'black'],
['brand' => 'Pagani', 'color' => 'orange'],
]);

$plucked = $collection->pluck('color', 'brand');

$plucked->all();

// ['Tesla' => 'black', 'Pagani' => 'orange']

pop()

pop 메서드는 컬렉션에서 마지막 항목을 꺼내 반환합니다:

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

$collection->pop();

// 5

$collection->all();

// [1, 2, 3, 4]

pop 메서드에 정수를 전달하면, 컬렉션의 끝에서 여러 항목을 꺼내 반환할 수 있습니다:

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

$collection->pop(3);

// collect([5, 4, 3])

$collection->all();

// [1, 2]

prepend()

prepend 메서드는 컬렉션의 맨 앞에 새 항목을 추가합니다:

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

$collection->prepend(0);

$collection->all();

// [0, 1, 2, 3, 4, 5]

두 번째 인수로, 앞에 추가할 항목의 키를 지정할 수도 있습니다:

$collection = collect(['one' => 1, 'two' => 2]);

$collection->prepend(0, 'zero');

$collection->all();

// ['zero' => 0, 'one' => 1, 'two' => 2]

pull()

pull 메서드는 컬렉션에서 특정 키에 해당하는 항목을 꺼내고, 그 값을 반환합니다:

$collection = collect(['product_id' => 'prod-100', 'name' => 'Desk']);

$collection->pull('name');

// 'Desk'

$collection->all();

// ['product_id' => 'prod-100']

push()

push 메서드는 컬렉션의 끝에 새 항목을 추가합니다:

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

$collection->push(5);

$collection->all();

// [1, 2, 3, 4, 5]

put()

put 메서드는 컬렉션에 주어진 키-값 쌍을 설정합니다:

$collection = collect(['product_id' => 1, 'name' => 'Desk']);

$collection->put('price', 100);

$collection->all();

// ['product_id' => 1, 'name' => 'Desk', 'price' => 100]

random()

random 메서드는 컬렉션에서 무작위로 항목 하나를 반환합니다.

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

$collection->random();

// 4 - (무작위로 선택됨)

무작위로 여러 개의 항목을 가져오고 싶다면 random에 정수 값을 인수로 전달할 수 있습니다. 가져올 항목의 개수를 명시적으로 지정하면, 항상 컬렉션이 반환됩니다.

$random = $collection->random(3);

$random->all();

// [2, 4, 5] - (무작위로 선택됨)

컬렉션 인스턴스에 요청한 개수보다 적은 항목이 있는 경우, random 메서드는 InvalidArgumentException 예외를 발생시킵니다.

random 메서드는 현재 컬렉션 인스턴스를 전달받는 클로저도 인수로 받을 수 있습니다.

use Illuminate\Support\Collection;

$random = $collection->random(fn (Collection $items) => min(10, count($items)));

$random->all();

// [1, 2, 3, 4, 5] - (무작위로 선택됨)

range()

range 메서드는 지정한 범위 내의 정수로 구성된 컬렉션을 반환합니다.

$collection = collect()->range(3, 6);

$collection->all();

// [3, 4, 5, 6]

reduce()

reduce 메서드는 컬렉션의 항목 전체를 하나의 값으로 축약합니다. 각 반복의 결과가 다음 반복으로 전달됩니다.

$collection = collect([1, 2, 3]);

$total = $collection->reduce(function (?int $carry, int $item) {
return $carry + $item;
});

// 6

첫 반복 시 $carry의 값은 null입니다. 하지만 두 번째 인수로 초기값을 지정할 수도 있습니다.

$collection->reduce(function (int $carry, int $item) {
return $carry + $item;
}, 4);

// 10

reduce 메서드는 연관 배열 컬렉션에서 배열의 키도 콜백 함수에 전달합니다.

$collection = collect([
'usd' => 1400,
'gbp' => 1200,
'eur' => 1000,
]);

$ratio = [
'usd' => 1,
'gbp' => 1.37,
'eur' => 1.22,
];

$collection->reduce(function (int $carry, int $value, int $key) use ($ratio) {
return $carry + ($value * $ratio[$key]);
});

// 4264

reduceSpread()

reduceSpread 메서드는 컬렉션을 여러 값이 담긴 배열로 축약합니다. 각 반복의 결과가 그다음 반복에 전달됩니다. 이 메서드는 reduce와 유사하지만, 여러 초기값을 지정할 수 있습니다.

[$creditsRemaining, $batch] = Image::where('status', 'unprocessed')
->get()
->reduceSpread(function (int $creditsRemaining, Collection $batch, Image $image) {
if ($creditsRemaining >= $image->creditsRequired()) {
$batch->push($image);

$creditsRemaining -= $image->creditsRequired();
}

return [$creditsRemaining, $batch];
}, $creditsAvailable, collect());

reject()

reject 메서드는 주어진 클로저를 사용해 컬렉션을 필터링합니다. 클로저가 true를 반환하는 항목은 결과 컬렉션에서 제외됩니다.

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

$filtered = $collection->reject(function (int $value, int $key) {
return $value > 2;
});

$filtered->all();

// [1, 2]

reject 메서드의 반대 동작이 필요하다면 filter 메서드를 참고하세요.

replace()

replace 메서드는 merge와 비슷하게 동작합니다. 다만, 문자열 키뿐만 아니라, 일치하는 숫자 키를 가진 컬렉션 항목도 덮어씁니다.

$collection = collect(['Taylor', 'Abigail', 'James']);

$replaced = $collection->replace([1 => 'Victoria', 3 => 'Finn']);

$replaced->all();

// ['Taylor', 'Victoria', 'James', 'Finn']

replaceRecursive()

이 메서드는 replace와 비슷하지만, 배열 내부까지 재귀적으로 들어가 내부 값에도 동일한 치환을 적용합니다.

$collection = collect([
'Taylor',
'Abigail',
[
'James',
'Victoria',
'Finn'
]
]);

$replaced = $collection->replaceRecursive([
'Charlie',
2 => [1 => 'King']
]);

$replaced->all();

// ['Charlie', 'Abigail', ['James', 'King', 'Finn']]

reverse()

reverse 메서드는 컬렉션 항목의 순서를 거꾸로 뒤집으며, 원래의 키도 그대로 유지합니다.

$collection = collect(['a', 'b', 'c', 'd', 'e']);

$reversed = $collection->reverse();

$reversed->all();

/*
[
4 => 'e',
3 => 'd',
2 => 'c',
1 => 'b',
0 => 'a',
]
*/

search 메서드는 지정한 값을 컬렉션에서 찾아서, 존재할 경우 해당 키를 반환합니다. 항목이 없다면 false를 반환합니다.

$collection = collect([2, 4, 6, 8]);

$collection->search(4);

// 1

이 검색은 "느슨한(loose)" 비교를 사용하므로, 정수와 동일한 값을 가진 문자열도 일치로 간주됩니다. "엄격한(strict)" 비교를 사용하고 싶다면 두 번째 인수에 true를 전달하세요.

collect([2, 4, 6, 8])->search('4', strict: true);

// false

또는 클로저를 제공하여, 주어진 조건을 통과하는 첫 번째 항목을 검색할 수도 있습니다.

collect([2, 4, 6, 8])->search(function (int $item, int $key) {
return $item > 5;
});

// 2

select()

select 메서드는 SQL의 SELECT 명령문처럼, 지정한 키만을 추출하여 새로운 컬렉션으로 반환합니다.

$users = collect([
['name' => 'Taylor Otwell', 'role' => 'Developer', 'status' => 'active'],
['name' => 'Victoria Faith', 'role' => 'Researcher', 'status' => 'active'],
]);

$users->select(['name', 'role']);

/*
[
['name' => 'Taylor Otwell', 'role' => 'Developer'],
['name' => 'Victoria Faith', 'role' => 'Researcher'],
],
*/

shift()

shift 메서드는 컬렉션에서 첫 번째 항목을 제거하고 반환합니다.

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

$collection->shift();

// 1

$collection->all();

// [2, 3, 4, 5]

shift 메서드에 정수를 인수로 전달하면, 컬렉션의 시작 부분에서 여러 개의 항목을 한번에 제거하고 반환할 수 있습니다.

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

$collection->shift(3);

// collect([1, 2, 3])

$collection->all();

// [4, 5]

shuffle()

shuffle 메서드는 컬렉션의 항목 순서를 무작위로 섞어 새로운 컬렉션을 만듭니다.

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

$shuffled = $collection->shuffle();

$shuffled->all();

// [3, 2, 5, 1, 4] - (무작위로 생성됨)

skip()

skip 메서드는 컬렉션의 앞에서 지정한 개수만큼 항목을 건너뛴 후, 나머지가 담긴 새 컬렉션을 반환합니다.

$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

$collection = $collection->skip(4);

$collection->all();

// [5, 6, 7, 8, 9, 10]

skipUntil()

skipUntil 메서드는 주어진 콜백이 false를 반환하는 동안은 항목을 건너뜁니다. 콜백이 처음으로 true를 반환하는 순간부터 나머지 모든 항목이 새로운 컬렉션으로 반환됩니다.

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

$subset = $collection->skipUntil(function (int $item) {
return $item >= 3;
});

$subset->all();

// [3, 4]

단순 값을 인수로 전달하면, 해당 값이 처음 나올 때까지 항목을 모두 건너뜁니다.

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

$subset = $collection->skipUntil(3);

$subset->all();

// [3, 4]

[!WARNING]
만약 주어진 값이 존재하지 않거나 콜백이 한번도 true를 반환하지 않는 경우, skipUntil 메서드는 빈 컬렉션을 반환합니다.

skipWhile()

skipWhile 메서드는 주어진 콜백이 true를 반환하는 동안 항목을 계속 건너뜁니다. 콜백이 처음으로 false를 반환하는 시점부터 남은 모든 항목이 새로운 컬렉션으로 반환됩니다.

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

$subset = $collection->skipWhile(function (int $item) {
return $item <= 3;
});

$subset->all();

// [4]

[!WARNING]
콜백이 한번도 false를 반환하지 않으면, skipWhile 메서드는 빈 컬렉션을 반환합니다.

slice()

slice 메서드는 지정된 인덱스부터 시작하는 컬렉션의 일부(슬라이스)를 반환합니다.

$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

$slice = $collection->slice(4);

$slice->all();

// [5, 6, 7, 8, 9, 10]

리턴되는 슬라이스의 크기를 제한하고 싶다면 두 번째 인수로 원하는 크기를 지정하면 됩니다.

$slice = $collection->slice(4, 2);

$slice->all();

// [5, 6]

기본적으로 반환된 슬라이스는 원본 키를 그대로 유지합니다. 원본 키를 유지하지 않고 연속된 인덱스로 재정렬하려면 values 메서드를 사용하세요.

sliding()

sliding 메서드는 컬렉션의 항목을 "슬라이딩 윈도우" 방식의 덩어리(chunk)로 만든 새 컬렉션을 반환합니다.

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

$chunks = $collection->sliding(2);

$chunks->toArray();

// [[1, 2], [2, 3], [3, 4], [4, 5]]

이 기능은 eachSpread 메서드와 함께 쓸 때 특히 유용합니다.

$transactions->sliding(2)->eachSpread(function (Collection $previous, Collection $current) {
$current->total = $previous->total + $current->amount;
});

두 번째 인수로 "스텝(step)" 값을 지정할 수 있는데, 이 값은 각 덩어리의 첫 항목 간 간격을 의미합니다.

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

$chunks = $collection->sliding(3, step: 2);

$chunks->toArray();

// [[1, 2, 3], [3, 4, 5]]

sole()

sole 메서드는 주어진 조건에 딱 하나만 부합하는 첫 번째 요소를 반환합니다.

collect([1, 2, 3, 4])->sole(function (int $value, int $key) {
return $value === 2;
});

// 2

키/값 쌍을 인수로 전달하면, 해당 쌍에 딱 하나만 일치하는 첫 번째 요소를 반환합니다.

$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 100],
]);

$collection->sole('product', 'Chair');

// ['product' => 'Chair', 'price' => 100]

또는 인수 없이 sole을 호출해서, 컬렉션에 항목이 단 하나만 있을 때 그 값을 바로 반환할 수도 있습니다.

$collection = collect([
['product' => 'Desk', 'price' => 200],
]);

$collection->sole();

// ['product' => 'Desk', 'price' => 200]

sole 메서드로 반환해야 할 항목이 없으면 \Illuminate\Collections\ItemNotFoundException 예외가 발생합니다. 반환해야 할 항목이 둘 이상이면 \Illuminate\Collections\MultipleItemsFoundException 예외가 발생합니다.

some()

contains 메서드의 별칭(alias)입니다.

sort()

sort 메서드는 컬렉션을 정렬합니다. 정렬된 컬렉션은 원래 배열의 키를 그대로 유지하므로, 아래 예시처럼 values 메서드를 사용하여 연속된 숫자 인덱스로 키를 재설정하는 방법을 참고하세요.

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

$sorted = $collection->sort();

$sorted->values()->all();

// [1, 2, 3, 4, 5]

더 복잡한 정렬이 필요하다면, 콜백을 전달하여 직접 알고리즘을 정의할 수 있습니다. sort 메서드는 내부적으로 PHP의 uasort 함수를 사용합니다.

[!NOTE]
중첩된 배열이나 객체로 구성된 컬렉션을 정렬하려면 sortBysortByDesc 메서드를 이용하세요.

sortBy()

sortBy 메서드는 지정한 키로 컬렉션을 정렬합니다. 정렬된 컬렉션은 원래 배열의 키를 유지하기 때문에, 예제처럼 values 메서드를 통해 키를 연속 번호로 재설정할 수 있습니다.

$collection = collect([
['name' => 'Desk', 'price' => 200],
['name' => 'Chair', 'price' => 100],
['name' => 'Bookcase', 'price' => 150],
]);

$sorted = $collection->sortBy('price');

$sorted->values()->all();

/*
[
['name' => 'Chair', 'price' => 100],
['name' => 'Bookcase', 'price' => 150],
['name' => 'Desk', 'price' => 200],
]
*/

sortBy 메서드는 두 번째 인수로 정렬 플래그를 지정할 수 있습니다.

$collection = collect([
['title' => 'Item 1'],
['title' => 'Item 12'],
['title' => 'Item 3'],
]);

$sorted = $collection->sortBy('title', SORT_NATURAL);

$sorted->values()->all();

/*
[
['title' => 'Item 1'],
['title' => 'Item 3'],
['title' => 'Item 12'],
]
*/

또한, 직접 클로저를 전달하여 컬렉션 값을 정렬하는 기준을 자유롭게 지정할 수도 있습니다.

$collection = collect([
['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
['name' => 'Chair', 'colors' => ['Black']],
['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
]);

$sorted = $collection->sortBy(function (array $product, int $key) {
return count($product['colors']);
});

$sorted->values()->all();

/*
[
['name' => 'Chair', 'colors' => ['Black']],
['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
]
*/

컬렉션을 여러 속성으로 정렬하고 싶다면, 각 정렬 조건을 배열로 지정하여 sortBy에 전달할 수 있습니다. 각 정렬 조건은 정렬하려는 속성과 정렬 방향을 지정하는 배열이어야 합니다.

$collection = collect([
['name' => 'Taylor Otwell', 'age' => 34],
['name' => 'Abigail Otwell', 'age' => 30],
['name' => 'Taylor Otwell', 'age' => 36],
['name' => 'Abigail Otwell', 'age' => 32],
]);

$sorted = $collection->sortBy([
['name', 'asc'],
['age', 'desc'],
]);

$sorted->values()->all();

/*
[
['name' => 'Abigail Otwell', 'age' => 32],
['name' => 'Abigail Otwell', 'age' => 30],
['name' => 'Taylor Otwell', 'age' => 36],
['name' => 'Taylor Otwell', 'age' => 34],
]
*/

여러 속성으로 정렬할 때도, 각각의 정렬 과정을 정의하는 클로저를 전달할 수 있습니다.

$collection = collect([
['name' => 'Taylor Otwell', 'age' => 34],
['name' => 'Abigail Otwell', 'age' => 30],
['name' => 'Taylor Otwell', 'age' => 36],
['name' => 'Abigail Otwell', 'age' => 32],
]);

$sorted = $collection->sortBy([
fn (array $a, array $b) => $a['name'] <=> $b['name'],
fn (array $a, array $b) => $b['age'] <=> $a['age'],
]);

$sorted->values()->all();

/*
[
['name' => 'Abigail Otwell', 'age' => 32],
['name' => 'Abigail Otwell', 'age' => 30],
['name' => 'Taylor Otwell', 'age' => 36],
['name' => 'Taylor Otwell', 'age' => 34],
]
*/

sortByDesc()

이 메서드는 sortBy 메서드와 동일한 시그니처를 가지지만, 컬렉션을 반대 순서로 정렬합니다.

sortDesc()

이 메서드는 컬렉션을 sort 메서드와는 반대 순서로 정렬합니다.

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

$sorted = $collection->sortDesc();

$sorted->values()->all();

// [5, 4, 3, 2, 1]

sort와는 달리, sortDesc에는 클로저를 전달할 수 없습니다. 직접 비교 로직을 반대로 하고 싶다면 sort 메서드를 사용해야 합니다.

sortKeys()

sortKeys 메서드는 내부의 연관 배열에서 키를 기준으로 컬렉션을 정렬합니다.

$collection = collect([
'id' => 22345,
'first' => 'John',
'last' => 'Doe',
]);

$sorted = $collection->sortKeys();

$sorted->all();

/*
[
'first' => 'John',
'id' => 22345,
'last' => 'Doe',
]
*/

sortKeysDesc()

이 메서드는 sortKeys 메서드와 동일한 시그니처를 가지며, 반대 순서로 컬렉션을 정렬합니다.

sortKeysUsing()

sortKeysUsing 메서드는 콜백 함수를 사용하여 내부 연관 배열의 키를 기준으로 컬렉션을 정렬합니다.

$collection = collect([
'ID' => 22345,
'first' => 'John',
'last' => 'Doe',
]);

$sorted = $collection->sortKeysUsing('strnatcasecmp');

$sorted->all();

/*
[
'first' => 'John',
'ID' => 22345,
'last' => 'Doe',
]
*/

콜백 함수는 정수값(음수, 0, 양수)을 반환하는 비교 함수여야 합니다. 더 자세한 정보는 PHP 공식 문서의 uksort를 참고하세요. sortKeysUsing 메서드는 내부적으로 이 PHP 함수를 사용합니다.

splice()

splice 메서드는 지정된 인덱스에서 시작하여 일정 개수의 항목을 제거하고 반환합니다.

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

$chunk = $collection->splice(2);

$chunk->all();

// [3, 4, 5]

$collection->all();

// [1, 2]

결과 컬렉션의 크기를 제한하고 싶다면 두 번째 인수로 제한할 크기를 전달할 수 있습니다.

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

$chunk = $collection->splice(2, 1);

$chunk->all();

// [3]

$collection->all();

// [1, 2, 4, 5]

또한, 제거된 항목 대신 새 항목을 추가하고 싶다면 세 번째 인수로 대체할 항목 배열을 전달할 수 있습니다.

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

$chunk = $collection->splice(2, 1, [10, 11]);

$chunk->all();

// [3]

$collection->all();

// [1, 2, 10, 11, 4, 5]

split()

split 메서드는 컬렉션을 지정한 개수의 그룹으로 나눕니다.

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

$groups = $collection->split(3);

$groups->all();

// [[1, 2], [3, 4], [5]]

splitIn()

splitIn 메서드는 컬렉션을 지정한 개수의 그룹으로 나눕니다. 이때 마지막 그룹을 제외한 다른 그룹들은 가능한 한 완전히 채워진 후, 남은 항목들을 마지막 그룹에 할당합니다.

$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

$groups = $collection->splitIn(3);

$groups->all();

// [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]

sum()

sum 메서드는 컬렉션 내 모든 항목을 더한 합계를 반환합니다.

collect([1, 2, 3, 4, 5])->sum();

// 15

컬렉션에 중첩 배열이나 객체가 포함되어 있다면, 합계를 구할 값을 결정할 키를 지정할 수 있습니다.

$collection = collect([
['name' => 'JavaScript: The Good Parts', 'pages' => 176],
['name' => 'JavaScript: The Definitive Guide', 'pages' => 1096],
]);

$collection->sum('pages');

// 1272

또한, 직접 콜백을 전달하여 합계를 구할 항목을 지정할 수도 있습니다.

$collection = collect([
['name' => 'Chair', 'colors' => ['Black']],
['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
]);

$collection->sum(function (array $product) {
return count($product['colors']);
});

// 6

take()

take 메서드는 지정한 개수만큼의 항목을 가진 새로운 컬렉션을 반환합니다.

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

$chunk = $collection->take(3);

$chunk->all();

// [0, 1, 2]

마지막에서부터 항목을 가져오고 싶다면 음수 값을 전달할 수 있습니다.

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

$chunk = $collection->take(-2);

$chunk->all();

// [4, 5]

takeUntil()

takeUntil 메서드는 지정한 콜백이 true를 반환할 때까지의 항목들을 반환합니다.

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

$subset = $collection->takeUntil(function (int $item) {
return $item >= 3;
});

$subset->all();

// [1, 2]

지정한 값이 나올 때까지 항목을 반환하고 싶다면 값을 직접 전달할 수도 있습니다.

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

$subset = $collection->takeUntil(3);

$subset->all();

// [1, 2]

[!WARNING]
전달한 값이 컬렉션에서 발견되지 않거나, 콜백이 한 번도 true를 반환하지 않는 경우, takeUntil 메서드는 컬렉션의 모든 항목을 반환합니다.

takeWhile()

takeWhile 메서드는 지정한 콜백이 false를 반환할 때까지의 항목들을 반환합니다.

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

$subset = $collection->takeWhile(function (int $item) {
return $item < 3;
});

$subset->all();

// [1, 2]

[!WARNING]
콜백이 한 번도 false를 반환하지 않으면, takeWhile 메서드는 컬렉션의 모든 항목을 반환합니다.

tap()

tap 메서드는 컬렉션 전체를 전달된 콜백에 넘겨주어, 컬렉션 자체는 변경하지 않은 채 특정 시점의 값들을 사용할 수 있도록 합니다. 이후 tap 메서드는 컬렉션을 그대로 반환합니다.

collect([2, 4, 3, 1, 5])
->sort()
->tap(function (Collection $collection) {
Log::debug('Values after sorting', $collection->values()->all());
})
->shift();

// 1

times()

정적 메서드인 times는 지정한 횟수만큼 클로저를 호출하여, 그 결과값으로 새로운 컬렉션을 만듭니다.

$collection = Collection::times(10, function (int $number) {
return $number * 9;
});

$collection->all();

// [9, 18, 27, 36, 45, 54, 63, 72, 81, 90]

toArray()

toArray 메서드는 컬렉션을 일반 PHP array로 변환합니다. 컬렉션 항목이 Eloquent 모델인 경우 모델도 배열로 변환됩니다.

$collection = collect(['name' => 'Desk', 'price' => 200]);

$collection->toArray();

/*
[
['name' => 'Desk', 'price' => 200],
]
*/

[!WARNING]
toArray는 컬렉션 내의 모든 하위 객체 중 Arrayable의 인스턴스도 배열로 변환합니다. 컬렉션의 실제 '원본' 배열만을 얻고 싶다면 all 메서드를 사용하세요.

toJson()

toJson 메서드는 컬렉션을 JSON 직렬화된 문자열로 변환합니다.

$collection = collect(['name' => 'Desk', 'price' => 200]);

$collection->toJson();

// '{"name":"Desk", "price":200}'

transform()

transform 메서드는 컬렉션을 순회하면서 각 항목을 콜백으로 전달하고, 콜백이 반환한 값으로 컬렉션의 항목을 교체합니다.

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

$collection->transform(function (int $item, int $key) {
return $item * 2;
});

$collection->all();

// [2, 4, 6, 8, 10]

[!WARNING]
대부분의 컬렉션 메서드와 달리, transform은 컬렉션 객체 자체를 직접 변경합니다. 새로운 컬렉션을 얻고 싶다면 대신 map 메서드를 사용하세요.

undot()

undot 메서드는 점(dot) 표기법을 사용한 1차원 컬렉션을 다차원 컬렉션으로 확장합니다.

$person = collect([
'name.first_name' => 'Marie',
'name.last_name' => 'Valentine',
'address.line_1' => '2992 Eagle Drive',
'address.line_2' => '',
'address.suburb' => 'Detroit',
'address.state' => 'MI',
'address.postcode' => '48219'
]);

$person = $person->undot();

$person->toArray();

/*
[
"name" => [
"first_name" => "Marie",
"last_name" => "Valentine",
],
"address" => [
"line_1" => "2992 Eagle Drive",
"line_2" => "",
"suburb" => "Detroit",
"state" => "MI",
"postcode" => "48219",
],
]
*/

union()

union 메서드는 주어진 배열을 컬렉션에 병합합니다. 만약 주어진 배열에 원본 컬렉션과 동일한 키가 있으면, 원본 컬렉션의 값을 우선으로 사용합니다.

$collection = collect([1 => ['a'], 2 => ['b']]);

$union = $collection->union([3 => ['c'], 1 => ['d']]);

$union->all();

// [1 => ['a'], 2 => ['b'], 3 => ['c']]

unique()

unique 메서드는 컬렉션에서 중복되지 않는 항목만 반환합니다. 반환된 컬렉션은 기존의 배열 키를 그대로 유지하므로, 아래의 예시처럼 values 메서드를 사용해 키를 연속적인 인덱스로 재설정할 수 있습니다.

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

$unique = $collection->unique();

$unique->values()->all();

// [1, 2, 3, 4]

중첩 배열이나 객체의 경우, 항목의 고유성을 판단할 키를 지정할 수 있습니다.

$collection = collect([
['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],
['name' => 'iPhone 5', 'brand' => 'Apple', 'type' => 'phone'],
['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'watch'],
['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],
['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'watch'],
]);

$unique = $collection->unique('brand');

$unique->values()->all();

/*
[
['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],
['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],
]
*/

또한, 고유성을 판단할 값을 직접 지정하기 위해 클로저를 전달할 수도 있습니다.

$unique = $collection->unique(function (array $item) {
return $item['brand'].$item['type'];
});

$unique->values()->all();

/*
[
['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],
['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'watch'],
['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],
['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'watch'],
]
*/

unique 메서드는 항목 값 비교 시 "느슨한(loose)" 비교를 사용합니다. 즉, 숫자형 문자열과 같은 값의 숫자가 같으면 동일하다고 간주됩니다. "엄격한(strict)" 비교를 사용해 필터링 하려면 uniqueStrict 메서드를 사용하세요.

[!NOTE]
이 메서드는 Eloquent 컬렉션을 사용할 때 동작이 달라집니다.

uniqueStrict()

이 메서드는 unique 메서드와 동일한 시그니처를 가지지만, 모든 값을 "엄격한(strict)" 비교로 판단하여 중복을 거릅니다.

unless()

unless 메서드는 첫 번째 인수가 true가 아닌 경우 주어진 콜백을 실행합니다.

$collection = collect([1, 2, 3]);

$collection->unless(true, function (Collection $collection) {
return $collection->push(4);
});

$collection->unless(false, function (Collection $collection) {
return $collection->push(5);
});

$collection->all();

// [1, 2, 3, 5]

두 번째 콜백을 전달할 수도 있습니다. 두 번째 콜백은 첫 번째 인수가 true로 평가되는 경우에 실행됩니다.

$collection = collect([1, 2, 3]);

$collection->unless(true, function (Collection $collection) {
return $collection->push(4);
}, function (Collection $collection) {
return $collection->push(5);
});

$collection->all();

// [1, 2, 3, 5]

unless의 반대 동작을 원하면 when 메서드를 참고하세요.

unlessEmpty()

whenNotEmpty 메서드의 별칭(aliase)입니다.

unlessNotEmpty()

whenEmpty 메서드의 별칭(aliase)입니다.

unwrap()

정적 메서드인 unwrap은 값을 받아 컬렉션이 적용 가능한 경우 컬렉션의 원본 항목을 반환합니다.

Collection::unwrap(collect('John Doe'));

// ['John Doe']

Collection::unwrap(['John Doe']);

// ['John Doe']

Collection::unwrap('John Doe');

// 'John Doe'

value()

value 메서드는 컬렉션의 첫 번째 요소에서 지정한 값을 추출합니다.

$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Speaker', 'price' => 400],
]);

$value = $collection->value('price');

// 200

values()

values 메서드는 키를 0부터 시작하는 연속적인 정수로 재설정한 새로운 컬렉션을 반환합니다.

$collection = collect([
10 => ['product' => 'Desk', 'price' => 200],
11 => ['product' => 'Desk', 'price' => 200],
]);

$values = $collection->values();

$values->all();

/*
[
0 => ['product' => 'Desk', 'price' => 200],
1 => ['product' => 'Desk', 'price' => 200],
]
*/

when()

when 메서드는 첫 번째 인자가 true로 평가될 때 지정한 콜백을 실행합니다. 이 콜백에는 컬렉션 인스턴스와 when 메서드에 전달한 첫 번째 인자가 전달됩니다.

$collection = collect([1, 2, 3]);

$collection->when(true, function (Collection $collection, int $value) {
return $collection->push(4);
});

$collection->when(false, function (Collection $collection, int $value) {
return $collection->push(5);
});

$collection->all();

// [1, 2, 3, 4]

when 메서드에는 두 번째 콜백도 전달할 수 있습니다. 두 번째 콜백은 첫 번째 인자가 false로 평가될 때 실행됩니다.

$collection = collect([1, 2, 3]);

$collection->when(false, function (Collection $collection, int $value) {
return $collection->push(4);
}, function (Collection $collection) {
return $collection->push(5);
});

$collection->all();

// [1, 2, 3, 5]

when의 반대 동작을 원하실 경우 unless 메서드를 참고하세요.

whenEmpty()

whenEmpty 메서드는 컬렉션이 비어 있을 때 지정한 콜백을 실행합니다.

$collection = collect(['Michael', 'Tom']);

$collection->whenEmpty(function (Collection $collection) {
return $collection->push('Adam');
});

$collection->all();

// ['Michael', 'Tom']
$collection = collect();

$collection->whenEmpty(function (Collection $collection) {
return $collection->push('Adam');
});

$collection->all();

// ['Adam']

whenEmpty 메서드에는 두 번째 클로저를 전달할 수 있으며, 컬렉션이 비어 있지 않을 때 이 두 번째 클로저가 실행됩니다.

$collection = collect(['Michael', 'Tom']);

$collection->whenEmpty(function (Collection $collection) {
return $collection->push('Adam');
}, function (Collection $collection) {
return $collection->push('Taylor');
});

$collection->all();

// ['Michael', 'Tom', 'Taylor']

whenEmpty의 반대 동작은 whenNotEmpty 메서드를 참고하세요.

whenNotEmpty()

whenNotEmpty 메서드는 컬렉션이 비어 있지 않을 때 지정한 콜백을 실행합니다.

$collection = collect(['michael', 'tom']);

$collection->whenNotEmpty(function (Collection $collection) {
return $collection->push('adam');
});

$collection->all();

// ['michael', 'tom', 'adam']
$collection = collect();

$collection->whenNotEmpty(function (Collection $collection) {
return $collection->push('adam');
});

$collection->all();

// []

whenNotEmpty 메서드에는 두 번째 클로저를 전달할 수 있으며, 컬렉션이 비어 있을 때 이 두 번째 클로저가 실행됩니다.

$collection = collect();

$collection->whenNotEmpty(function (Collection $collection) {
return $collection->push('adam');
}, function (Collection $collection) {
return $collection->push('taylor');
});

$collection->all();

// ['taylor']

whenNotEmpty의 반대 동작은 whenEmpty 메서드를 참고하세요.

where()

where 메서드는 지정한 키/값 쌍으로 컬렉션을 필터링합니다.

$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 100],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Door', 'price' => 100],
]);

$filtered = $collection->where('price', 100);

$filtered->all();

/*
[
['product' => 'Chair', 'price' => 100],
['product' => 'Door', 'price' => 100],
]
*/

where 메서드는 값을 비교할 때 "느슨한(loose)" 비교를 사용합니다. 즉, 정수 값과 같은 값을 가진 문자열은 정수 값과 같다고 간주합니다. "엄격한(strict)" 비교를 사용하려면 whereStrict 메서드를 사용하세요.

선택적으로 두 번째 인자로 비교 연산자를 전달할 수 있습니다. 지원되는 연산자는 ===, !==, !=, ==, =, <>, >, <, >=, <=입니다.

$collection = collect([
['name' => 'Jim', 'deleted_at' => '2019-01-01 00:00:00'],
['name' => 'Sally', 'deleted_at' => '2019-01-02 00:00:00'],
['name' => 'Sue', 'deleted_at' => null],
]);

$filtered = $collection->where('deleted_at', '!=', null);

$filtered->all();

/*
[
['name' => 'Jim', 'deleted_at' => '2019-01-01 00:00:00'],
['name' => 'Sally', 'deleted_at' => '2019-01-02 00:00:00'],
]
*/

whereStrict()

이 메서드는 where 메서드와 사용법이 동일하지만 모든 값을 "엄격한(strict)" 비교로 비교합니다.

whereBetween()

whereBetween 메서드는 지정한 아이템의 값이 주어진 범위에 포함되는지 여부로 컬렉션을 필터링합니다.

$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 80],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Pencil', 'price' => 30],
['product' => 'Door', 'price' => 100],
]);

$filtered = $collection->whereBetween('price', [100, 200]);

$filtered->all();

/*
[
['product' => 'Desk', 'price' => 200],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Door', 'price' => 100],
]
*/

whereIn()

whereIn 메서드는 주어진 배열에 포함된 특정 아이템 값을 갖지 않는 요소들을 컬렉션에서 제거합니다.

$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 100],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Door', 'price' => 100],
]);

$filtered = $collection->whereIn('price', [150, 200]);

$filtered->all();

/*
[
['product' => 'Desk', 'price' => 200],
['product' => 'Bookcase', 'price' => 150],
]
*/

whereIn 메서드는 값을 비교할 때 "느슨한(loose)" 비교를 사용합니다. 즉, 정수 값과 같은 값을 가진 문자열은 정수 값과 같다고 간주합니다. "엄격한(strict)" 비교를 사용하려면 whereInStrict 메서드를 사용하세요.

whereInStrict()

이 메서드는 whereIn 메서드와 사용법이 동일하지만 모든 값을 "엄격한(strict)" 비교로 비교합니다.

whereInstanceOf()

whereInstanceOf 메서드는 지정한 클래스 타입의 인스턴스만 필터링하여 컬렉션에서 반환합니다.

use App\Models\User;
use App\Models\Post;

$collection = collect([
new User,
new User,
new Post,
]);

$filtered = $collection->whereInstanceOf(User::class);

$filtered->all();

// [App\Models\User, App\Models\User]

whereNotBetween()

whereNotBetween 메서드는 지정한 아이템의 값이 주어진 범위를 벗어나는 경우만 필터링하여 컬렉션에 남깁니다.

$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 80],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Pencil', 'price' => 30],
['product' => 'Door', 'price' => 100],
]);

$filtered = $collection->whereNotBetween('price', [100, 200]);

$filtered->all();

/*
[
['product' => 'Chair', 'price' => 80],
['product' => 'Pencil', 'price' => 30],
]
*/

whereNotIn()

whereNotIn 메서드는 주어진 배열에 포함된 아이템 값을 갖는 요소들을 컬렉션에서 제거합니다.

$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 100],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Door', 'price' => 100],
]);

$filtered = $collection->whereNotIn('price', [150, 200]);

$filtered->all();

/*
[
['product' => 'Chair', 'price' => 100],
['product' => 'Door', 'price' => 100],
]
*/

whereNotIn 메서드는 값을 비교할 때 "느슨한(loose)" 비교를 사용합니다. 즉, 정수 값과 같은 값을 가진 문자열은 정수 값과 같다고 간주합니다. "엄격한(strict)" 비교를 사용하려면 whereNotInStrict 메서드를 사용하세요.

whereNotInStrict()

이 메서드는 whereNotIn 메서드와 사용법이 동일하지만 모든 값을 "엄격한(strict)" 비교로 비교합니다.

whereNotNull()

whereNotNull 메서드는 주어진 키가 null이 아닌 요소만 컬렉션에서 반환합니다.

$collection = collect([
['name' => 'Desk'],
['name' => null],
['name' => 'Bookcase'],
]);

$filtered = $collection->whereNotNull('name');

$filtered->all();

/*
[
['name' => 'Desk'],
['name' => 'Bookcase'],
]
*/

whereNull()

whereNull 메서드는 주어진 키가 null인 요소만 컬렉션에서 반환합니다.

$collection = collect([
['name' => 'Desk'],
['name' => null],
['name' => 'Bookcase'],
]);

$filtered = $collection->whereNull('name');

$filtered->all();

/*
[
['name' => null],
]
*/

wrap()

정적 메서드인 wrap은 전달된 값을 컬렉션으로 감쌀 수 있을 때 컬렉션으로 감쌉니다.

use Illuminate\Support\Collection;

$collection = Collection::wrap('John Doe');

$collection->all();

// ['John Doe']

$collection = Collection::wrap(['John Doe']);

$collection->all();

// ['John Doe']

$collection = Collection::wrap(collect('John Doe'));

$collection->all();

// ['John Doe']

zip()

zip 메서드는 지정한 배열의 값과 원래 컬렉션의 값을 같은 인덱스끼리 병합해서 반환합니다.

$collection = collect(['Chair', 'Desk']);

$zipped = $collection->zip([100, 200]);

$zipped->all();

// [['Chair', 100], ['Desk', 200]]

하이어 오더 메시지(Higher Order Messages)

컬렉션은 "하이어 오더 메시지(higher order messages)"도 지원합니다. 이는 컬렉션에서 자주 사용하는 동작을 더 간단하게 호출할 수 있는 단축 표현 방식입니다. 하이어 오더 메시지를 지원하는 컬렉션 메서드는 average, avg, contains, each, every, filter, first, flatMap, groupBy, keyBy, map, max, min, partition, reject, skipUntil, skipWhile, some, sortBy, sortByDesc, sum, takeUntil, takeWhile, unique 등이 있습니다.

각 하이어 오더 메시지는 컬렉션 인스턴스의 동적 속성처럼 접근할 수 있습니다. 예를 들어 컬렉션 내 각 객체에서 메서드를 호출하려면, each 하이어 오더 메시지를 다음과 같이 사용할 수 있습니다.

use App\Models\User;

$users = User::where('votes', '>', 500)->get();

$users->each->markAsVip();

마찬가지로, sum 하이어 오더 메시지를 사용해 users 컬렉션의 "votes" 값을 모두 합칠 수도 있습니다.

$users = User::where('group', 'Development')->get();

return $users->sum->votes;

레이지 컬렉션(Lazy Collections)

소개

[!WARNING]
라라벨의 레이지 컬렉션을 학습하기 전에, PHP 제너레이터(generators)를 먼저 확인해보시는 것이 좋습니다.

기존의 강력한 Collection 클래스에 더해, LazyCollection 클래스는 PHP의 제너레이터(generators)를 활용하여 매우 큰 데이터셋도 메모리를 적게 사용하면서 다룰 수 있게 해줍니다.

예를 들어, 애플리케이션에서 수 기가바이트의 로그 파일을 처리해야 하는데, 라라벨 컬렉션 메서드를 그대로 사용해서 로그 파일을 분석하고 싶다고 가정해 보겠습니다. 전체 파일을 한 번에 메모리로 읽어들이는 대신, 레이지 컬렉션을 사용하면 특정 순간 필요한 일부 데이터만 메모리에 읽어서 처리할 수 있습니다.

use App\Models\LogEntry;
use Illuminate\Support\LazyCollection;

LazyCollection::make(function () {
$handle = fopen('log.txt', 'r');

while (($line = fgets($handle)) !== false) {
yield $line;
}
})->chunk(4)->map(function (array $lines) {
return LogEntry::fromLines($lines);
})->each(function (LogEntry $logEntry) {
// 로그 엔트리 처리...
});

또 다른 예로, 만약 10,000개의 Eloquent 모델을 반복문으로 순회해야 하는 경우를 생각해 보세요. 일반적인 라라벨 컬렉션을 사용할 경우, 이 모든 Eloquent 모델이 한 번에 메모리로 로드됩니다.

use App\Models\User;

$users = User::all()->filter(function (User $user) {
return $user->id > 500;
});

하지만 쿼리 빌더의 cursor 메서드는 LazyCollection 인스턴스를 반환합니다. 이를 사용하면 데이터베이스에 쿼리는 한 번만 실행하면서, 한 번에 하나의 Eloquent 모델만 메모리에 올릴 수 있습니다. 이 예제에서는 실제로 각 사용자(user)를 한 명씩 반복문으로 순회할 때까지 filter 콜백이 실행되지 않아, 메모리 사용량이 혁신적으로 줄어듭니다.

use App\Models\User;

$users = User::cursor()->filter(function (User $user) {
return $user->id > 500;
});

foreach ($users as $user) {
echo $user->id;
}

레이지 컬렉션 인스턴스 생성하기

레이지 컬렉션 인스턴스를 만들려면, PHP 제너레이터 함수를 컬렉션의 make 메서드에 전달하면 됩니다.

use Illuminate\Support\LazyCollection;

LazyCollection::make(function () {
$handle = fopen('log.txt', 'r');

while (($line = fgets($handle)) !== false) {
yield $line;
}
});

Enumerable 계약(Enumerable Contract)

대부분의 Collection 클래스에서 사용할 수 있는 메서드는 LazyCollection 클래스에서도 사용 가능합니다. 이 두 클래스는 모두 Illuminate\Support\Enumerable 계약을 구현하며, 아래와 같은 메서드를 정의합니다:

[!WARNING]
컬렉션을 변경하는 메서드(예: shift, pop, prepend 등)는 LazyCollection 클래스에서는 사용할 수 없습니다.

지연 컬렉션 메서드

Enumerable 계약에 정의된 메서드 외에도, LazyCollection 클래스에는 다음과 같은 추가 메서드들이 포함되어 있습니다.

takeUntilTimeout()

takeUntilTimeout 메서드는 지정된 시간까지 컬렉션의 값을 순회(enumerate)하도록 동작하는 새로운 지연(lazy) 컬렉션을 반환합니다. 해당 시간이 지나면 컬렉션의 순회를 중단합니다.

$lazyCollection = LazyCollection::times(INF)
->takeUntilTimeout(now()->addMinute());

$lazyCollection->each(function (int $number) {
dump($number);

sleep(1);
});

// 1
// 2
// ...
// 58
// 59

이 메서드의 사용 예시로, 커서를 이용해 데이터베이스에서 송장(invoice)을 제출하는 애플리케이션을 상상해 보십시오. 예를 들어, 15분마다 실행되는 스케줄러 작업을 정의한 뒤, 최대 14분 동안만 송장을 처리할 수 있습니다.

use App\Models\Invoice;
use Illuminate\Support\Carbon;

Invoice::pending()->cursor()
->takeUntilTimeout(
Carbon::createFromTimestamp(LARAVEL_START)->add(14, 'minutes')
)
->each(fn (Invoice $invoice) => $invoice->submit());

tapEach()

each 메서드는 컬렉션의 각 항목에 대해 즉시 주어진 콜백을 호출하지만, tapEach 메서드는 항목이 하나씩 리스트에서 꺼내지는 시점에만 콜백을 호출합니다.

// 아직 아무 것도 dump되지 않습니다...
$lazyCollection = LazyCollection::times(INF)->tapEach(function (int $value) {
dump($value);
});

// 아래에서 세 개의 항목이 dump됩니다...
$array = $lazyCollection->take(3)->all();

// 1
// 2
// 3

throttle()

throttle 메서드는 지연(lazy) 컬렉션을 지정한 초(sec)만큼 간격을 두고 반환하게 만듭니다. 이 메서드는 외부 API와 연동하며 요청 속도를 제한해야 하는 상황(예: 외부에서 인입되는 요청의 처리 속도 제한)에서 특히 유용합니다.

use App\Models\User;

User::where('vip', true)
->cursor()
->throttle(seconds: 1)
->each(function (User $user) {
// 외부 API 호출...
});

remember()

remember 메서드는 이미 순회한(enumerated) 값을 기억하여, 동일한 컬렉션을 다시 순회할 때 데이터를 다시 조회하지 않고 캐시된 값을 반환하는 새로운 지연 컬렉션을 반환합니다.

// 아직 쿼리가 실행되지 않았습니다...
$users = User::cursor()->remember();

// 여기서 쿼리가 실행됩니다...
// 처음 5명의 사용자가 데이터베이스에서 불러와집니다...
$users->take(5)->all();

// 처음 5명의 사용자는 컬렉션의 캐시에서 가져오고...
// 나머지는 데이터베이스에서 불러와집니다...
$users->take(20)->all();