- カテゴリ: collection
- 掲載バージョン: Laravel 12・PHP 8.4
- 名前空間 / FQCN / コマンド:
Illuminate\Support\Collection::pipe - 関連: tap / when / unless / pipeInto / map
- 変更履歴: 特記なし
要点(TL;DR)
- コレクション自身をコールバックに渡し、その戻り値をそのまま返すためのメソッド
- 例:
$sum = collect([1,2,3])->pipe(fn ($c) => $c->sum()); - 罠:
- チェーンは続かないことがある(コールバックが配列や数値を返すと以後はコレクションではない)
tapと違い元のコレクションは返らない- 型を厳密にすると
TypeErrorになりやすい(Collection型ヒントの不一致)
概要
pipeは、現在のコレクションをコールバックにそのまま渡し、コールバックの戻り値を返すユーティリティです。
「この時点のコレクションを一旦別関数・サービスに渡して、結果を受け取りたい」場面で有効です。結果はコレクションに限らず、数値・配列・DTO など任意です。
構文 / シグネチャ
public function pipe(callable $callback): mixed;
引数(表)
| 引数 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|
| $callback | callable(Collection $collection): mixed | ✔︎ | — | コレクションを受け取り、任意の値を返す関数/クロージャ |
- 戻り値:
mixed(コールバックの戻り値そのもの) - 例外/副作用:コールバック内で発生した例外がそのまま伝播。
pipe自体は非破壊でコレクションを変更しない。
使用例
最小例
<?php
declare(strict_types=1);
use Illuminate\Support\Collection;
require __DIR__.'/vendor/autoload.php';
$sum = collect([1, 2, 3])->pipe(fn (Collection $c) => $c->sum());
echo $sum; // 6
実務例
サービスクラスに委譲して集計→配列で返す。
<?php
declare(strict_types=1);
use Illuminate\Support\Collection;
require __DIR__.'/vendor/autoload.php';
final class OrderStats
{
public function __invoke(Collection $orders): array
{
return [
'count' => $orders->count(),
'revenue' => $orders->sum('amount'),
'byStatus'=> $orders->groupBy('status')->map->count()->all(),
];
}
}
$orders = collect([
['id' => 1, 'amount' => 1200, 'status' => 'paid'],
['id' => 2, 'amount' => 800, 'status' => 'pending'],
['id' => 3, 'amount' => 500, 'status' => 'paid'],
]);
$stats = $orders->pipe(new OrderStats());
/*
$stats = [
'count' => 3,
'revenue' => 2500,
'byStatus' => ['paid' => 2, 'pending' => 1],
];
*/
コールバックがコレクションを返せば、チェーン継続も可能:
$names = collect([['name' => 'ann'], ['name' => 'Bob']])
->pipe(fn (Collection $c) => $c->pluck('name')) // Collection を返す
->map(fn ($n) => ucfirst($n))
->values(); // ['Ann', 'Bob']
よくある落とし穴・注意
- チェーン断絶:コールバックが非コレクションを返すと、以降はコレクションメソッドを呼べません。続けたい場合はコールバックで
Collectionを返すか、最後にcollect()で包み直します。 tapとの違い:tapは副作用を与えて元のコレクションを返す/pipeはコールバックの戻り値を返す。- LazyCollection:
pipeの引数としてLazyCollectionが渡る場合、評価はコールバック次第。集計等で反復するとその時点でイテレーションが走ります。 - 型ヒント:
callable(Collection $c)のように型指定するなら、渡るのがLazyCollectionかCollectionかを意識する(両対応にするならIlluminate\Contracts\Support\Arrayable|iterableなど柔らかい受け方も検討)。
代替・関連APIとの比較
- tap:副作用を書いても元のコレクションでチェーン継続したい →
tap - when / unless:条件に応じて処理をチェーン内で分岐したい →
when/unless - pipeInto:コレクションを特定クラスのコンストラクタへ入力したい →
pipeInto(Foo::class) - map:要素ごとの変換をしたい →
map(pipeは全体を一括で扱う) - Pipeline(Illuminate\Pipeline):複数ステップを通過させる処理の構造化 → アプリ全体のパイプラインに
テスト例(Pest)
<?php
use Illuminate\Support\Collection;
it('pipes collection to callback and returns its result', function () {
$result = collect([1, 2, 3])->pipe(fn (Collection $c) => $c->sum());
expect($result)->toBe(6);
});
it('does not mutate the original collection', function () {
$c = collect([1, 2, 3]);
$c->pipe(fn (Collection $x) => $x->sum());
expect($c->all())->toBe([1, 2, 3]);
});
トラブルシュート(エラー別)
| 症状/エラー | 原因 | 対処 |
|---|---|---|
Call to a member function map() on array | pipeで配列を返した後にコレクションメソッドを呼んだ | コールバックでCollectionを返す/collect($array)で包む |
TypeError: Argument 1 must be of type Collection | コールバックの型ヒントと実際に渡るインスタンスが不一致(LazyCollection等) | 型ヒントを緩めるか、collect()でCollectionへ変換してから渡す |
| 想定外に重い/遅い | LazyCollectionに対して集計等で全件評価している | 遅延評価の理解を前提に、必要範囲で評価/ストリーム処理へ分割 |
コレクション固有の付記
- チェーン可否:コールバックが
Collectionを返す場合のみ継続可 - 破壊的/非破壊:非破壊
- キー保持:コールバックに依存(戻り値が
Collectionなら、そのロジックに従う) - LazyCollection 対応:可
- 計算量の目安:
O(1)(コールバックの計算量に依存)
入出力対応の小サンプル
| 入力 | コールバック | 出力 |
|---|---|---|
Collection([1,2,3]) | sum() を返す | int(6) |
Collection([['n'=>'a'],['n'=>'b']]) | pluck('n') を返す | Collection(['a','b']) |
LazyCollection($gen) | count() を返す | int(評価が走る) |
参考リンク
- Laravel Docs — Collections: pipe(Laravel 12): https://laravel.com/docs/12.x/collections#method-pipe
- Laravel Docs — Collections: tap: https://laravel.com/docs/12.x/collections#method-tap
- Laravel Docs — Collections: when / unless: https://laravel.com/docs/12.x/collections#method-when
- Laravel Docs — Collections: pipeInto: https://laravel.com/docs/12.x/collections#method-pipeinto
- Illuminate\Pipeline — Pipeline(概念と比較): https://laravel.com/docs/12.x/pipelines
