追記 2009/03/01 20:40
ソースにすこし手を加えたところ消えなくなったので、検証中…
追記 2009/03/01 22:07
Debian(squeeze/testing)にソースからビルドして入れたところ、やっぱり消えました。
array_unique関数がPHP5.2.9から後方互換性を失いました - hnwの日記
はてなブックマーク - array_unique関数がPHP5.2.9から後方互換性を失いました - hnwの日記
heavenshell php マジかよ。自分じゃほぼ使わないけど、FW とかライブラリで使ってるだろこれ | grep -r "array_unique" library/Zend | wc -l → 21 | zf じゃ 21 箇所で使ってる模様
hnw symfonyだとsfToolkit::arrayDeepMerge()が2配列のキーをarray_mergeしたものをarray_uniqueしてますな。どうみても影響があります。本当に(ry
CakePHPでは?
% cd ~/local/lib % grep -r "array_unique" ./cakephp1.2.1.8004 | wc -l 13 % grep -r "array_unique" ./cakephp1.2.1.8004 ./cakephp1.2.1.8004/cake/console/cake.php: $this->shellPaths = array_values(array_unique(array_merge($paths, Configure::read('shellPaths')))); ./cakephp1.2.1.8004/cake/console/libs/tasks/extract.php: $storage[$file][1] = array_unique(array_merge($storage[$file][1], $fileList)); ./cakephp1.2.1.8004/cake/console/libs/tasks/extract.php: @$output[$this->__filename][1] = array_unique(array_merge($output[$this->__filename][1], $content[1])); ./cakephp1.2.1.8004/cake/libs/controller/components/security.php: $fieldList += array_unique($multi); ./cakephp1.2.1.8004/cake/libs/model/behaviors/containable.php: $query['fields'] = array_unique($query['fields']); ./cakephp1.2.1.8004/cake/libs/model/behaviors/containable.php: $Model->{$type}[$dependency]['fields'] = array_unique(array_merge($Model->{$type}[$dependency]['fields'], $innerFields)); ./cakephp1.2.1.8004/cake/libs/model/behaviors/containable.php: return array_unique($fields); ./cakephp1.2.1.8004/cake/libs/model/datasources/dbo_source.php: 'fields' => array_unique($queryData['fields']), ./cakephp1.2.1.8004/cake/libs/model/datasources/dbo_source.php: 'fields' => array_unique($assocData['fields']), ./cakephp1.2.1.8004/cake/libs/model/datasources/dbo_source.php: return array_unique($fields); ./cakephp1.2.1.8004/cake/libs/model/model.php: $ids = array_unique(Set::extract('/' . $this->alias . '/parent_id', $return)); ./cakephp1.2.1.8004/cake/libs/model/model.php: return array($with, array_unique(array_merge($assoc[$with], $keys))); ./cakephp1.2.1.8004/cake/libs/set.php: $keys = array_unique($keys);
Set::sortで消える
grepしただけで影響がありそうだった、Setクラスを調べてみました。
Set::sort()でソートすると、値が消えるサンプルを作りました。
sample_controller.php
(修正 Set::sortの第二引数を'{[a-z0-9]+}.Person.value'→'{[a-zA-Z0-9]+}.Person.value'に修正)
<?php class SampleController extends AppController { var $uses = array(); function index() { $test = array( '1e1' => array('Person' => array('value' => '1')), '10' => array('Person' => array('value' => '2')), ); debug(Set::sort($test, '{[a-zA-Z0-9]+}.Person.value', 'desc')); } }
php5.2.6 on debian(squeeze/testing)での実行結果
app/controllers/sample_controller.php (line 8) 5.2.6-3 app/controllers/sample_controller.php (line 13) Array ( [0] => Array ( [Person] => Array ( [value] => 2 ) ) [1] => Array ( [Person] => Array ( [value] => 1 ) ) )
消える組み合わせ
ひとつになりました。
// ... 略 $test = array( '1e1' => array('Person' => array('value' => '1')), '10' => array('Person' => array('value' => '2')), '0x0a' => array('Person' => array('value' => '3')), '010' => array('Person' => array('value' => '4')), ); debug(Set::sort($test, '{[a-zA-Z0-9]+}.Person.value', 'desc')); // ... 略
Array ( [0] => Array ( [Person] => Array ( [value] => 4 ) ) )
コメントより
hnw 浮動小数点数を使わなくても、'0'と'Z'とかでも消えると思います。連想配列のキーは整数にできる場合は数値になるので、今回のarray_uniqueの仕様変更が凶悪に効いてきます。
調べてみました。
// ... 略 $test = array( '0' => array('Person' => array('value' => '5')), 'Z' => array('Person' => array('value' => '6')), ); debug(Set::sort($test, '{[a-zA-Z0-9]+}.Person.value', 'desc')); // ... 略
Array ( [0] => Array ( [Person] => Array ( [value] => 6 ) ) )
本当に消えた…なぜ?ちょっと調べてみました。
…わかった、と思います。
まず、上記のサンプルの '0'というキー配列を定義したあとvar_dumpしてみると、intになりました。(この時点で「えーっ」と思うのですが)
そして、キーだったものを比較すると、
var_dump('0' == "Z"); // false var_dump(0 == "Z"); // true
0と'Z'が等しいとなります。この比較演算子の挙動はhttp://jp.php.net/manual/ja/language.operators.comparison.phpを見れば分かりますが、stringとintの比較はstring型を数値に変換してから比較します(int型とは限らない)。(string→数値の変換については…以下略)