CakePHP 2.2以降で利用できるHashクラスのcombineメソッドには以下の罠があります。
Code:
< ?php
$data = [
[
'id' => 1,
'title' => 'first title',
'body' => 'first content'
],
[
'id' => 3,
'title' => 'second title',
'body' => 'second content',
'more' => 'second more content'
],
[
'id' => 5,
'title' => 'third title',
'body' => 'third content',
'more' => 'third more content'
],
];
$results = Hash::combine($data, '{n}.id', '{n}.more');
この場合、$resultsは以下の値になることを期待するでしょう。
$results = [
1 => null,
3 => 'second more content',
5 => 'third more content',
];
しかし、実際には以下のように、キーと値の組み合わせがずれてしまいます。
$results = [
1 => 'second more content',
3 => 'third more content',
5 => null,
];
一体なぜ、このようなことが起るのでしょう。
Hash::combine
では、内部でHash::extract
を利用しているので、指定のパスからキーおよび値を抽出する際、指定したパスに値がない場合は切り詰められます。
内部処理としては以下のようなイメージです。
$keys = Hash::extract($data, '{n}.id');
// -> [1, 3, 5]
$values = Hash::extract($data, '{n}.more');
// -> ['second more content', 'third more content']
return array_combine($keys, $values);
結合時に単純にarray_combine
で結合すれば、キーと値の数が違う場合、E_WARNING
が発生するので気付くのですが、我らがCakePHPは余計なことをしてくれています。
cakephp/lib/Cake/Utility/Hash.php at 2.4.3 · cakephp/cakephp
はい、数があわない場合、nullで値を埋めます。
もうわけがわからないよ。。。
というわけで、Issueは上げておきました。そのうち、この場合は例外を発生するように修正されるはずです。タブン。
2013-12-24追記
CakePHP 2.4.4以降、CakeExceptionが発生するように修正されました。
Throw exceptions from Hash::combine() · 62e8973 · cakephp/cakephp