CakePHP 2.2以降で利用できるHashクラスのcombineメソッドには以下の罠があります。
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
< ?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は以下の値になることを期待するでしょう。
1 2 3 4 5 6 7 8 |
$results = [ 1 => null, 3 => 'second more content', 5 => 'third more content', ]; |
しかし、実際には以下のように、キーと値の組み合わせがずれてしまいます。
1 2 3 4 5 6 7 8 |
$results = [ 1 => 'second more content', 3 => 'third more content', 5 => null, ]; |
一体なぜ、このようなことが起るのでしょう。
Hash::combine
では、内部でHash::extract
を利用しているので、指定のパスからキーおよび値を抽出する際、指定したパスに値がない場合は切り詰められます。
内部処理としては以下のようなイメージです。
1 2 3 4 5 6 7 8 9 |
$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