【PHP】変数・定数の比較で注意すべき事
IT事業部 プログラマーのTKです。
1か月ぶりの投稿です。
今回はPHPの変数・定数の使用の仕方で注意すべき点を書きます。
PHPの変数・定数を定義する時は、型指定をあらかじめ行う必要が有りません。
変数は”$hoge”のように先頭にドル記号を付けるだけで変数として扱う事が可能です。
定数も文字列なり数値なりをそのまま定義するだけで簡単に済みます。
しかし、それ故に変数にどんな値が入っているかプログラマが意識して
コードを記述しないと、意図しない動作をさせてしまう事があります。
例えば、筆者が社内向けシステムを開発した際に、
部署に応じて機能を分岐させる実装を行う上で躓いた例を取り上げてみます。
(実際のコードよりかなり簡略化しております。)
実行環境:PHP version 5.3.3
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 26 27 28 29 30 31 |
<?php //部署コードの定数 define('EXTENT_HONSHA',7); define('EXTENT_SHISHA',8); print("空文字<br>"); compare_test(""); print("本社<br>"); compare_test(EXTENT_HONSHA); print("支社<br>"); compare_test(EXTENT_SHISHA); print("その他_文字列<br>"); compare_test("6"); print("その他_数値<br>"); compare_test(6); print("複数_文字列<br>"); compare_test("7,10"); function compare_test($section){ if($section == ""){ //部署コード未設定の場合 print("★部署コード★未設定<br>"); }elseif($section == EXTENT_HONSHA){ //部署コード「本社」の場合 print("★部署コード★本社<br>"); }elseif($section == EXTENT_SHISHA){ //部署コード「支社」の場合 print("★部署コード★支社<br>"); }else{ print("★部署コード★その他<br>"); } } ?> |
出力結果:
空文字
★部署コード★未設定
本社
★部署コード★本社
支社
★部署コード★支社
その他_文字列
★部署コード★その他
その他_数値
★部署コード★その他
複数_文字列
★部署コード★本社
カンマ区切りのデータを渡した際に、
“★部署コード★その他”へ処理が進むかと思いきや、
“★部署コード★本社”へ処理が進んでしまいます。
実は、PHPでは数値と文字列を比較しようとすると
暗黙的に文字列を数値にキャストしてしまう仕様になっています。
しかも文字列の先頭に数値、途中から英字、記号等が入っている場合は、
それ以降の部分をぶった切って数値だけを取得してしまう様です。
この為、文字列”7,10″のうち、先頭の数値’7’だけを認識して比較するので、
人間の感覚とややずれた、意図しない挙動をとる事になります。
こういった仕様のずれを回避するには、
以下のような実装を行います。
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 26 27 28 |
<?php print("空文字<br>"); compare_test_Fixed(""); print("本社<br>"); compare_test_Fixed(EXTENT_HONSHA); print("支社<br>"); compare_test_Fixed(EXTENT_SHISHA); print("その他_文字列<br>"); compare_test_Fixed("6"); print("その他_数値<br>"); compare_test_Fixed(6); print("複数_文字列<br>"); compare_test_Fixed("7,10"); function compare_test_Fixed($section){ if($section === ""){ //部署コード未設定の場合 print("★部署コード★未設定<br>"); }elseif($section === EXTENT_HONSHA){ //部署コード「本社」の場合 print("★部署コード★本社<br>"); }elseif($section === EXTENT_SHISHA){ //部署コード「支社」の場合 print("★部署コード★支社<br>"); }else{ print("★部署コード★その他<br>"); } } ?> |
出力結果:
空文字
★部署コード★未設定
本社
★部署コード★本社
支社
★部署コード★支社
その他_文字列
★部署コード★その他
その他_数値
★部署コード★その他
複数_文字列
★部署コード★その他
if文で比較を行う際に値が等しいか(==演算子)だけでなく、
型も等しいか(===演算子)をチェックする必要があります。
PHPでは動的に型定義ができるメリットがありますが、
意識して変数・定数を使わないと思いがけない不具合を作りこんでしまう可能性が
ありますので、注意すべき所です。