2011年10月12日

PHP:array_key_existsより array自体がヤバいんじゃないか?

互換性のために作った array_intersect_key を見直していて、ふと不思議な文をマニュアルに見つけた。それが下の一文。

「二つの要素は、 (string) $elem1 === (string) $elem2 の場合のみ等しいとみなされます。言い替えると、厳密なチェックが行われるため、文字列表現が同じである必要があります。」
(つたない英語力だが英語サイトも同様)
ref) http://www.php.net/manual/en/function.array-intersect-key.php

一瞬「え?」です。

ここで配列の基本の幾つか。

  1. key は、整数 または 文字列です。

  2. 整数の標準的な表現形式である場合、 そのように解釈されます (つまり、"8" は 8 として解釈されます。一方、 "08" は "08" として解釈されます)。


ref) http://www.php.net/manual/ja/language.types.array.php

つまり、厳密であろうと曖昧であろうと、key は「重ならない」と思っていたわけです。つまり array(1 => value1, "1" => value2) と定義しても array(1 => value2) と解釈される。そのため array_key_exists に strict が無くても問題はなく、isset のような恐ろしく曖昧なものより信用していたんですね。それなのに array_intersect_key の場合は、string への型変換後に厳密なチェック云々とはどういうこっちゃ? と。array の性質上すでに解決済みのハズ。

で、この前書いた。
PHP:array_key_exists のバグ?
http://zombiebook.seesaa.net/article/228944224.html
がまざまざと蘇る訳です。
しょーがなので、イヤイヤ試すと案の定といいますか……。
(※ 今回は Windows, php 5.2.4 のみで検査です)

array(
 '2147483647' => int 0,
 2147483647 => int 0,
);

あらまあやっちゃってるよ。コノ人。上記2のルールが解決されてない。そう思うと array_key_exists には strict だとどこにも書いてないが、strict だとしたらそっちのほうが正しい動きをしていた訳だ。むしろ array が悪い子じゃん。まあ、内部的にいつ解釈されるのか知りませんが、var_dump の結果です。

本来なら。
array(
 2147483647 => int 0,
);
になるはず。

これ放置するのオカシイよね? こんな基本的な事ホントに既知じゃないの? 5.2 までスルー? それとも私が何か読み落としてる?

既知かどうか、色々調べようかと思ったけど……。
なんだかどうでも良くなってきた。ハァ……。php 嫌いじゃないんだけどねぇ。なんだか型宣言が必要な言語が懐かしくなってきたよ。

ちなみに1
int max は設定できる。これを設定しなおすとどうなるか不明。

ちなみに2
キーが想定できない場合 $ary[$key] で走査する部分は危険かもしれない。具体的には for や foreach よりも each でペアを取った方が安全。もう調べる気力も試す気力もないが。

個人的に以下はエラーにすべきだと。検査してはいるが存在自体気分悪い。
key に浮動小数点数値を指定すると、 その値は integer に切り詰められます。キーとして TRUE を使用した場合、 整数型の 1 がキーとして解釈されます。 キーとして FALSE を使用した場合、 整数型の 0 がキーとして解釈されます。 キーとして NULL を使用した場合、 空の文字列として評価されます。




posted by HiFa at 00:31 | 愛知 ☁ | Comment(0) | TrackBack(0) | ときどきPHP | このブログの読者になる | 更新情報をチェックする
>>> スパムコメントは消してますよん。 お互い無駄な労力は避けましょう。 <<<

この記事へのコメント

コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック