$collection = collect([collect([1, 2, 3, 4, 5]), collect([6, 7, 8, 9, 10])])->map(function ($collection) {
return $collection->average();
});
$collection = collect([collect([1, 2, 3, 4, 5]), collect([6, 7, 8, 9, 10])])->map->average();
上を下のようにメソッドチェーンで繋げられるようにしたものです。
collect([collect([1, 2, 3, 4, 5]), collect([6, 7, 8, 9, 10])])->map
で__get()
メソッドを呼びHigherOrderCollectionProxy
オブジェクトを返します。
public function __get($key)
{
if (! in_array($key, static::$proxies)) {
throw new Exception("Property [{$key}] does not exist on this collection instance.");
}
return new HigherOrderCollectionProxy($this, $key);
}
phpではクラスに存在しないプロパティ(ここではmap)を読み込むとマジックメソッド__get()
を呼び出します。
$key
はプロはティ名の文字列です。
そしてstatic::$proxies
の中にmapが入っているかをチェックしてから、HigherOrderCollectionProxy
を返します。
第一引数にはcollect([collect([1, 2, 3, 4, 5]), collect([6, 7, 8, 9, 10])])
、
第二引数には'map'
が入ります。
/**
* The methods that can be proxied.
*
* @var array
*/
protected static $proxies = [
'average', 'avg', 'contains', 'each', 'every', 'filter', 'first',
'flatMap', 'groupBy', 'keyBy', 'map', 'max', 'min', 'partition',
'reject', 'some', 'sortBy', 'sortByDesc', 'sum', 'unique',
];
public function __construct(Collection $collection, $method)
{
$this->method = $method;
$this->collection = $collection;
}
$this->method
に'map'
、$this->collection
にCollection
オブジェクトが入ります。
そして->average()
を呼び出します。
HigherOrderCollectionProxy
にはaverage()
メソッドはないので、マジックメソッド__call()
が呼ばれます。
/**
* Proxy a method call onto the collection items.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
return $this->collection->{$this->method}(function ($value) use ($method, $parameters) {
return $value->{$method}(...$parameters);
});
}
$method
はメソッド名の文字列(ここでは'average'
)、$parameters
は引数を格納した入れ配列(average()
は引数がないので空の配列)になります。
つまり__call()
の中身は
return $this->collection->map(function ($value) use ('average', []) {
return $value->average(...[]);
});
ということになります。
/**
* Run a map over each of the items.
*
* @param callable $callback
* @return static
*/
public function map(callable $callback)
{
$keys = array_keys($this->items);
$items = array_map($callback, $this->items, $keys);
return new static(array_combine($keys, $items));
}
$callback
はfunction ($value) use ('average', []) { return $value->average(...[]); }
、
$this->items
は[collect([1, 2, 3, 4, 5]), collect([6, 7, 8, 9, 10])]
、
$keys
は[0, 1]
です。
array_map() は、array1 の各要素に callback 関数を適用した後、 その全ての要素を含む配列を返します。
つまり__call()
の$value
にはそれぞれ、collect([1, 2, 3, 4, 5]とcollect([6, 7, 8, 9, 10])が入ります。
そしてaverage()
で平均が計算され
var_dump($collection->all());
/*
array(2) {
[0]=>
int(3)
[1]=>
int(8)
}
*/
となります。