- カテゴリ: collection
- 掲載バージョン: Laravel 12・PHP 8.4
- 名前空間 / FQCN / コマンド:
Illuminate\Support\Collection::transform - 関連: map / mapInto / mapSpread / values / each
- 変更履歴: 旧来からのメソッド。
mapとの違い(破壊的)に注意。
要点(TL;DR)
- 何に使うか:全要素をコールバックで変換して元のコレクション自体を書き換える
- 最低限の使い方:
$c->transform(fn ($v, $k) => /* 変換 */); - よくある罠:
mapと違い破壊的(同じインスタンスを書き換え)- キーは保持。添字を詰めたいなら
values()を併用 - LazyCollectionは基本非推奨(遅延処理には
mapを使う)
概要
transformは、各要素にコールバックを適用し、その結果で元のコレクションの要素を置き換えます。mapの“非破壊”版に対し、transformは“破壊的”で、同じ変数を後段でも使う場面では副作用に注意します。キーは保持されるため、連番が必要ならvalues()で再採番します。
構文 / シグネチャ
public function transform(callable $callback): static
引数(表)
| 引数 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|
$callback | callable(mixed $value, mixed $key): mixed | ✓ | – | 各要素を受け取り、置き換える値を返す |
- 戻り値:
Collection(同一インスタンス) - 例外/副作用:元のコレクション内容が直接変更される(共有参照に注意)
使用例
最小例
<?php
use Illuminate\Support\Collection;
$prices = collect([100, 200, 300]);
$prices->transform(fn ($p) => (int) round($p * 1.1)); // 破壊的
// $prices は [110, 220, 330]
キー保持の例
<?php
$stock = collect(['AAPL' => 180, 'MSFT' => 420]);
$stock->transform(fn ($v, $symbol) => $symbol . ':' . $v);
// キーは ['AAPL', 'MSFT'] のまま
実務例(Eloquent→API用DTOへ)
<?php
use App\Models\User;
$users = User::where('active', true)->get(); // Collection<App\Models\User>
// 同じ $users を API用配列に“上書き”する
$users->transform(function ($u) {
return [
'id' => $u->id,
'name' => $u->name,
'joined_at' => $u->created_at->toDateString(),
];
});
return response()->json($users); // ここでモデルではなく配列の集合になっている点に注意
よくある落とし穴・注意
- 破壊的:後続で元のモデル/オブジェクトが必要なら
mapを使うか、$copy = $c->map(...);のように別変数へ。 - キー保持:連番にしたい場合は
$c->values()をチェーン。 - LazyCollection:遅延評価ストリームでは
transformよりmapを使う(transformは非遅延・一括処理向き)。 - 型変更の副作用:モデルを配列へ変えた後に、モデル前提の処理(
$user->idなど)を続けると壊れる。
代替・関連APIとの比較
map:非破壊で新しいコレクションを返す。副作用を避けたい/チェーンで元を残したいならこちら。each:返り値は元要素(変更しない)。副作用(ログ出力等)向け。mapInto(Foo::class):各要素を指定クラスのインスタンスへ変換。mapSpread:配列要素を引数として展開して変換。values:キーをリセットして0からの連番へ。
選定基準:
- 元コレクションを上書きしたい →
transform - 元を残したい/遅延したい →
map
テスト例(Pest)
<?php
use Illuminate\Support\Collection;
it('transforms in place and keeps keys', function () {
$c = collect(['a' => 1, 'b' => 2]);
$id = spl_object_id($c);
$c->transform(fn ($v) => $v * 10);
expect($c->all())->toBe(['a' => 10, 'b' => 20])
->and(spl_object_id($c))->toBe($id); // 同一インスタンス
});
コレクション特性(カテゴリ規約)
- チェーン可否:可(同一インスタンスを返す)
- 破壊的/非破壊:破壊的
- キー保持:保持する
- LazyCollection:非推奨(遅延処理は
mapを使用) - 計算量:O(n)
入出力対応サンプル
| 入力 | 変換 | 出力 |
|---|---|---|
[1,2,3] | *2 | [2,4,6](キー0,1,2のまま) |
['a'=>1,'b'=>2] | +10 | ['a'=>11,'b'=>12](キー維持) |
トラブルシュート(エラー別)
| 症状/エラー | 原因 | 対処 |
|---|---|---|
Call to undefined method transform | 配列に対して呼んでいる | 先にcollect($arr)でコレクション化 |
| モデルのプロパティ参照が壊れた | transform後に要素を配列へ変換してしまった | 非破壊のmapを使う/別変数に代入 |
| 連番にしたいのにキーが詰まらない | transformはキーを保持する | 後続でvalues()を呼ぶ |
参考リンク
- Laravel公式:Collections — transform
https://laravel.com/docs/12.x/collections#method-transform - API:
Illuminate\Support\Collection
https://laravel.com/api/12.x/Illuminate/Support/Collection.html - ソースコード(Collection)
https://github.com/laravel/framework/blob/12.x/src/Illuminate/Support/Collection.php - 関連:
map(非破壊)
https://laravel.com/docs/12.x/collections#method-map

