cakePHP(v3.x)、indexByとgroupByの使い分け

collection Class において、groupByを利用することで、あるプロパティをキーに持つ配列を作ることができます。

$people = [
    ['name' => 'Tanaka', 'age' => 9, ],
    ['name' => 'Yamada', 'age' => 10, ],
    ['name' => 'Honda', 'age' => 10, ],
    ['name' => 'Yamamoto', 'age' => 9, ]
];
$collection = new Collection($people);
$peopleByAge = $collection->groupBy('age')->toArray();

// 結果
[
  10 => [
    ['name' => 'Yamada', 'age' => 10],
    ['name' => 'Honda', 'age' => 10]
  ],
  9 => [
    ['name' => 'Tanaka', 'age' => 9],
    ['name' => 'Yamamoto', 'age' => 9]
  ]
]

上の例では年齢をキーに持つ連想配列を取得することができます。

しかし、あるプロパティが一意の値を持つことがわかっている場合、indexByを利用すると以下のような構造を得ることができます。(ここでは名前をkeyにします。)

$people = [
    ['name' => 'Tanaka', 'age' => 9, ],
    ['name' => 'Yamada', 'age' => 10, ],
    ['name' => 'Honda', 'age' => 10, ],
    ['name' => 'Yamamoto', 'age' => 9, ]
];
$collection = new Collection($people);
$peopleByAge = $collection->indexBy('name')->toArray();

// 結果
[
  'Tanaka'=> ['name' => 'Tanaka', 'age' => 9, ],
  'Yamada' => ['name' => 'Yamada', 'age' => 10, ],
  'Honda' => ['name' => 'Honda', 'age' => 10, ],
  'Yamamoto' =>  ['name' => 'Yamamoto', 'age' => 9, ]
]

これをgroupByでやってしまうと配列が不本意に多重になってしまうので、こういった場面にはindexByを使いましょう。

$people = [
    ['name' => 'Tanaka', 'age' => 9, ],
    ['name' => 'Yamada', 'age' => 10, ],
    ['name' => 'Honda', 'age' => 10, ],
    ['name' => 'Yamamoto', 'age' => 9, ]
];
$collection = new Collection($people);
$peopleByAge = $collection->groupBy('name')->toArray();

// 結果
[
  'Tanaka'=> [['name' => 'Tanaka', 'age' => 9, ]],
  'Yamada' => [['name' => 'Yamada', 'age' => 10, ]],
  'Honda' => [['name' => 'Honda', 'age' => 10, ]],
  'Yamamoto' =>  [['name' => 'Yamamoto', 'age' => 9, ]]
]