logo header
logo header
logo header
logo header
  • 2016.08.16
  • 技術ブログ開発

PHPの意外な落とし穴を見てみましょう

YOSX9687_TP_V 2

こんにちは、農道JSです。

夏になりましたね。 北海道の夏といったら、ビーチで焼き肉をするのが私は好きです。

ただ、焼き肉を食べた後、ビーチで散歩する時、ふざけて、うかつにちゃんと目の前のことを見ないと、落とし穴にはまるリスクがあります。

という事で、今回は「PHPの意外な落とし穴」を挙げたいと思います。

1. 文字列の加算

PHPで文字列の加算ができます。 まず基本ですが、普通(整数)の加算の例:

コード

出力すると…

これは誰でも想定できる結果だと思います。

さて、文字列で加算を試しましょう。下記のコードでいろいろな文字列を定義して、加算して、出力します:

コード

上記はどういう結果になるでしょう?

結果は以下のとおりです:

出力すると…

1と5行目は一番納得できると思いますが、2~4行目の結果について、「何じゃこれ」と思う人もいると思います。

PHPは、後ろから英数字の加算を行い、(文字列の)数値は整数と同じような増分になり、英字は次の文字(A→B、など)になります。

英数字以外のは対象外のため、5行目は変更なしになります。

ちなみに:

  • '19'はちゃんと'20'になる
  • 'z'は'aa'になる(つまり、'tesz'は'teta'になる)
  • 'B'は'C'になる(大文字は大文字になる、小文字は小文字になる)
  • 'test!z'は'test!a'になる

2. 「==」対「===」の夏祭り!

PHPを使ったことのある人にとって、PHPにおけるJavaScriptでいうところの「==」と「===」の比較演算子の違いは少なくとも、何となくわかりながらも、わかりにくい側面もあります。

「==」をざっくり説明すると、type jugglingして値を比較します。

「===」をざっくり説明すると、型も値も比較します。

コード

出力すると…

上記からいろんなことが確認できます:

  • 「'hoge'」は「TRUE」と同じ、後「'hoge'」は「0」と同じですが、「TRUE」は「0」と同じではない…
  • 「54」は「'54hoge'」と同じですが、「'54'」は「'54hoge'」と同じではない…
  • 「'123'」は「'0123'」と同じですが、「123」は「0123」と同じではない
  • 「'2e3'」は「'2000'」と同じ…

キレイな説明になりませんが、「==」を使うと、PHPはできる限り数値に変換します。「できる限り」は浮動小数点までになります。その影響で、「md5('240610708') == md5('QNKCDZO')」は「TRUE」になります…

ちなみに、「===」は型も値も比較しますが、オブジェクトであれば、まったく同じオブジェクトではない限り、「TRUE」になりません。ただ、「==」でオブジェクトを比較するとそのオブジェクトの各属性の型と値の比較になります…

3. 超break

PHPを使ったことがある人は「break」を使ったことがあるかもしれません:

コード

出力すると…

不思議な動きではないと思いますが、下記はいかがですか?

コード

出力すると…

…そうです。PHPでは、「break 2;」は、breakは2回実行されます。 (もちろん、「3」など他の数値もできます) PHP 5.4.0まで「break $variable;」もできました。

これはステキな道具なのか、GOTO的な異端なのか…いろいろ意見はあります。

特別賞

最後に、特別賞:

出力すると…

ともに世界をアップグレードできる、そんな日を夢見て。
Upgrade the World!