Posted at

Laravelのmap, filter, reduceとか

More than 1 year has passed since last update.

Laravel(5.4) Eloquent のクエリは Collection を返します。

初めは何だこれ?と思ったのですが、実はかなり便利だったので簡単な紹介です。

$ php artisan tinker

Psy Shell v0.8.1 (PHP 7.1.1 cli) by Justin Hileman
>>> collect(range(1, 10));
=> Illuminate\Support\Collection {#694
all: [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
],
}
>>> collect(range(1, 10))->filter(function($n) { return $n % 2 == 0; });
=> Illuminate\Support\Collection {#725
all: [
1 => 2,
3 => 4,
5 => 6,
7 => 8,
9 => 10,
],
}
>>> collect(range(1, 10))->filter(function($n) { return $n % 2 == 0; })->map(function($n) { return $n * 2; })
=> Illuminate\Support\Collection {#702
all: [
1 => 4,
3 => 8,
5 => 12,
7 => 16,
9 => 20,
],
}
>>> collect(range(1, 10))->filter(function($n) { return $n % 2 == 0; })->map(function($n) { return $n * 2; })->reduce(function($carry, $n) { return $carry + $n; });
=> 60

メソッドチェーンで簡単に繋げるのがいいですね。

他にもphpの標準関数の代替となる色々便利なメソッドがあるので、以下を一度見てみると良いです。

ちなみに普通の配列だと

>>> array_filter(range(1, 10), function($n) { return $n % 2 == 0; })

=> [
1 => 2,
3 => 4,
5 => 6,
7 => 8,
9 => 10,
]
>>> array_map(
... function($n) { return $n * 2; },
... array_filter(range(1, 10), function($n) { return $n % 2 == 0; })
... );
=> [
1 => 4,
3 => 8,
5 => 12,
7 => 16,
9 => 20,
]
>>> array_reduce(
... array_map(
... function($n) { return $n * 2; },
... array_filter(range(1, 10), function($n) { return $n % 2 == 0; })
... ),
... function($carry, $n) { return $carry + $n; }
... );
=> 60

とてもワンライナーでは書く気がしないし array_map のcallbackの引数の位置が他と違って読みにくいですね。

なので Laravel 使ってて map とか filter とか reduce したいなら配列はとりあえず collect に渡しちゃえば幸せになれるっていう話でした。