コレクション

コレクションクラスは、配列(またはTraversableオブジェクト)を操作するためのメソッドを提供する。

コレクションの生成

<?php

use Cake\Collection\Collection;

$items = ['apple', 'banana', 'kiwi'];
$collection = new Collection($items);

?>

反復処理に関するメソッド

each

コレクション内の各オブジェクトに対して関数を実行する。

<?php
$collection->each(function ($value, $key) {
    echo "要素 $key: $value";
});
?>
map

コレクション内の各オブジェクトに対して関数を実行し、新しいコレクションを返す。

<?php
$new = $collection->map(function ($value, $key) {
    return $value * 2;
});
?>
extract

特定のプロパティの値を含むコレクションを作成する。

<?php
$collection = new Collection($people);
$names = $collection->extract('name');

// $result には ['mark', 'jose', 'barbara'] が含まれています。
$result = $names->toList();
?>

取得したいプロパティがパスで表現できない場合は、それを返すようにコールバック関数を使用できる。

<?php
$collection = new Collection($articles);
$names = $collection->extract(function ($article) {
    return $article->author->name . ', ' . $article->author->last_name;
});
?>
combine

combine('keyにするプロパティ', 'valueにするプロパティ'); で、キーと値から作られた新しいコレクションを作成できる。

<?php
$items = [
    ['id' => 1, 'name' => 'foo', 'parent' => 'a'],
    ['id' => 2, 'name' => 'bar', 'parent' => 'b'],
    ['id' => 3, 'name' => 'baz', 'parent' => 'a'],
];
$combined = (new Collection($items))->combine('id', 'name');

// 配列に変換すると、結果は次のようになります。
[
    1 => 'foo',
    2 => 'bar',
    3 => 'baz',
];
?>
unfold

すべての要素に対する反復処理が一回で済むように、コレクションの内部構造を平坦化する。

<?php
$items = [[1, 2, 3], [4, 5]];
$collection = new Collection($items);
$new = $collection->unfold();

// $result には [1, 2, 3, 4, 5] が含まれています。
$result = $new->toList();
?>
chunk

コレクションを任意の大きさに分割する。連想配列を分割する場合は、chunkWithKeys()を用いる。

<?php
$items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
$collection = new Collection($items);
$chunked = $collection->chunk(2);
$chunked->toList(); // [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11]]
?>

フィルタリングに関するメソッド

filter

基準のコールバックに一致する要素の新しいコレクションを生成する。逆に一致する要素を取り除いたコレクションを生成する場合は、reject()を用いる。

<?php
$collection = new Collection($people);
$ladies = $collection->filter(function ($person, $key) {
    return $person->gender === 'female';
});
?>
every

コレクションのすべての要素がコールバックの条件を満たしているかを判定する。少なくとも1つの要素が条件を満たしているかを判定する場合は、some()を用いる。

<?php
$collection = new Collection($people);
$ladies = $collection->filter(function ($person, $key) {
    return $person->gender === 'female';
});
?>
match

指定したプロパティの特定の値を持つ要素の新しいコレクションを生成する。最初に一致した要素を取得する場合は、firstMatch()を用いる。

<?php
$collection = new Collection($comments);
$commentsFromMark = $collection->match(['user.name' => 'Mark']);
?>

要素の取得に関するメソッド

sample

指定した数の要素を取得する。

<?php
$collection = new Collection($people);

// このコレクションからランダムに最大 20 ユーザーを取り出します。
$testSubjects = $collection->sample(20);
?>
take

コレクションのスライスを取得する。

<?php
// ポジション 4 から始まるコレクションから5人取り出します。
$nextTopFive = $collection->sortBy('age')->take(5, 4);
?>
first

コレクションの最初の要素を取得する。最後の要素を取得する場合はlast()を用いる。

<?php
$collection = new Collection([5, 4, 3, 2]);
$collection->first(); // 戻り値は 5
?>

集約に関するメソッド

reduce

コレクションの各要素の値を集約し一つの値を取得する。reduceの第一引数のコールバックの第一引数に集約した値を格納する変数、第二引数にコレクションの要素を表す変数を渡す。reduceの第二引数は初期値。

<?php
$totalPrice = $collection->reduce(function ($accumulated, $orderLine) {
    return $accumulated + $orderLine->price;
}, 0); // $accumulatedの初期値
?>
min

指定したプロパティの値が最小である要素を取得する。最大である要素を取得する場合はmax()を用いる。

<?php
$collection = new Collection($people);
$youngest = $collection->min('age');
?>
sumOf

すべての要素の指定したプロパティの値の合計を取得する。

<?php
$collection = new Collection($people);
$sumOfAges =  $collection->sumOf('age');
?>
avg

すべての要素の指定したプロパティの値の平均を取得する。中央値を取得する場合はmedian()を用いる。

<?php
$items = [
   ['invoice' => ['total' => 100]],
   ['invoice' => ['total' => 200]],
];

// 平均値: 150
$average = (new Collection($items))->avg('invoice.total');
?>
groupBy

コレクションの要素がプロパティに同じ値を持つ場合、キー別にグループ化した新しいコレクションを取得できる。

<?php
$students = [
    ['name' => 'Mark', 'grade' => 9],
    ['name' => 'Andrew', 'grade' => 10],
    ['name' => 'Stacy', 'grade' => 10],
    ['name' => 'Barbara', 'grade' => 9]
];
$collection = new Collection($students);
$studentsByGrade = $collection->groupBy('grade');

// 配列に変換すると、結果は次のようになります。
[
  10 => [
    ['name' => 'Andrew', 'grade' => 10],
    ['name' => 'Stacy', 'grade' => 10]
  ],
  9 => [
    ['name' => 'Mark', 'grade' => 9],
    ['name' => 'Barbara', 'grade' => 9]
  ]
]
?>

コールバックを渡すことで動的にコレクションを生成できる。

<?php
$classResults = $students->groupBy(function ($student) {
    return $student->grade > 6 ? 'approved' : 'denied';
});
?>
countBy

グループごとの出現数を取得する。

<?php
$classResults = $students->countBy(function ($student) {
    return $student->grade > 6 ? 'approved' : 'denied';
});

// 配列に変換すると、結果は次のようになります。
['approved' => 70, 'denied' => 20]
?>

ソートに関するメソッド

sortBy

指定したプロパティによってソートされた新しいコレクションを取得する。デフォルトでは降順並べ替えになっており、昇順の場合は第二引数にSORT_ASCを渡す。

<?php
$collection = new Collection($people);
$sorted = $collection->sortBy('age');
$sorted = $collection->sortBy('age', SORT_ASC); // 昇順

$sorted_by_association = $collection->sortBy('address.country'); // 関連するモデルの値でソート
?>

コレクションの拡張に関するメソッド

append

複数のコレクションから、両方のソースの値を含む新しい一つのコレクションを生成する。

<?php
// cakephpに関するツイートとphpに関するツイートのコレクションを統合
$cakephpTweets = new Collection($tweets);
$myTimeline = $cakephpTweets->append($phpTweets);

// 両方のソースから cakefest を含むつぶやきを取得
$myTimeline->filter(function ($tweet) {
    return strpos($tweet, 'cakefest');
});
?>
appendItem

オプションのキーを持つアイテムをコレクションに追加する。

<?php
$cakephpTweets = new Collection($tweets);
$myTimeline = $cakephpTweets->appendItem($newTweet, 99);
?>

その他のメソッド

<?php
$collection->isEmpty(); // コレクションに要素が含まれているか確認
$collection->contains('foo'); // コレクションに特定の値が含まれているか確認
$collection->shuffle(); // 要素の順序をシャッフル
?>