CakePHP Hash::combine() でキーと値の組み合わせがずれる

標準

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は上げておきました。そのうち、この場合は例外を発生するように修正されるはずです。タブン。

Hash::combine() returns incorrect key-value pair, when value path not found · Issue #2470 · cakephp/cakephp

2013-12-24追記

CakePHP 2.4.4以降、CakeExceptionが発生するように修正されました。

Throw exceptions from Hash::combine() · 62e8973 · cakephp/cakephp

コメントを残す

Page optimized by WP Minify WordPress Plugin