本当は怖いPHP

2,769 views
2,608 views

Published on

第11回 LOCAL PHP部 勉強会
http://php.local.or.jp/

使用フォント:http://www.ankokukoubou.com/font/hakidame.htm

http://labs.nazone.info/

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
2,769
On SlideShare
0
From Embeds
0
Number of Embeds
18
Actions
Shares
0
Downloads
10
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • irb(main):001:0> (0.1+0.7)*10 => 8.0 irb(main):002:0> ((0.1+0.7)*10).to_int => 7
  • bool のキャスト= if の判定と同じ 1=>true 0=>false " "=>true ""=>false "0"=>false array()=>false null=>false "000"+0=>false 0+"00.0"=>false if の時は === をちゃんと使おう array のキャスト=その値を push した配列が出来上がる object のキャスト array=>object のキャスト object=>array のキャスト なんと相互変換ができる PHP 怖い 謎のキャスト unset null になる(それだけ) 別に変数が unset されるわけでもなく謎
  • http://d.hatena.ne.jp/hnw/20090227
  • http://d.hatena.ne.jp/hnw/20090227
  • http://d.hatena.ne.jp/hnw/20090227
  • bool のキャスト= if の判定と同じ 1=>true 0=>false " "=>true ""=>false "0"=>false array()=>false null=>false "000"+0=>false 0+"00.0"=>false if の時は === をちゃんと使おう array のキャスト=その値を push した配列が出来上がる object のキャスト array=>object のキャスト object=>array のキャスト なんと相互変換ができる PHP 怖い 謎のキャスト unset null になる(それだけ) 別に変数が unset されるわけでもなく謎
  • bool のキャスト= if の判定と同じ 1=>true 0=>false " "=>true ""=>false "0"=>false array()=>false null=>false "000"+0=>false 0+"00.0"=>false if の時は === をちゃんと使おう array のキャスト=その値を push した配列が出来上がる object のキャスト array=>object のキャスト object=>array のキャスト なんと相互変換ができる PHP 怖い 謎のキャスト unset null になる(それだけ) 別に変数が unset されるわけでもなく謎
  • bool のキャスト= if の判定と同じ 1=>true 0=>false " "=>true ""=>false "0"=>false array()=>false null=>false "000"+0=>false 0+"00.0"=>false if の時は === をちゃんと使おう array のキャスト=その値を push した配列が出来上がる object のキャスト array=>object のキャスト object=>array のキャスト なんと相互変換ができる PHP 怖い 謎のキャスト unset null になる(それだけ) 別に変数が unset されるわけでもなく謎
  • bool のキャスト= if の判定と同じ 1=>true 0=>false " "=>true ""=>false "0"=>false array()=>false null=>false "000"+0=>false 0+"00.0"=>false if の時は === をちゃんと使おう array のキャスト=その値を push した配列が出来上がる object のキャスト array=>object のキャスト object=>array のキャスト なんと相互変換ができる PHP 怖い 謎のキャスト unset null になる(それだけ) 別に変数が unset されるわけでもなく謎
  • bool のキャスト= if の判定と同じ 1=>true 0=>false " "=>true ""=>false "0"=>false array()=>false null=>false "000"+0=>false 0+"00.0"=>false if の時は === をちゃんと使おう array のキャスト=その値を push した配列が出来上がる object のキャスト array=>object のキャスト object=>array のキャスト なんと相互変換ができる PHP 怖い 謎のキャスト unset null になる(それだけ) 別に変数が unset されるわけでもなく謎
  • 本当は怖いPHP

    1. 1. 本当は怖い PHP 第 11 回 LOCAL PHP 部勉強会 LOCAL PHP 部 nazo
    2. 2. 夏もそろそろ 終わりですね
    3. 3. 今回は PHP にまつわる 怪談をご紹介します
    4. 4. 今回の主なネタ元 http://d.hatena.ne.jp/hnw/ http://d.hatena.ne.jp/moriyoshi/
    5. 5. 01 本当は怖い isset
    6. 6. ある日、一人の少年が 配列をチェックしていました。 「配列に指定した要素があるかどうかを調べるんだから isset だよねー」 if (isset($array[“hoge”])) { ...
    7. 7. ところがある日 $array が配列ではなく文字列になってしまいました
    8. 8. $array = “foo”; if (isset($array[“hoge”])) { // ここは実行される
    9. 9. ぎゃあああああああああ
    10. 10. 文字列に対する[]参照 <ul><li>指定位置の一文字を取得する
    11. 11. $a = “foo”; $a[1] => “o”
    12. 12. 強制的に数字
    13. 13. 数字以外を入れるとキャストされる
    14. 14. (int)“hoge” => 0
    15. 15. $a[0] </li></ul>
    16. 16. おお、こわいこわい
    17. 17. この発表面白いんだろうか…
    18. 18. 02 本当は怖い 32bit ※ これは PHP とは関係ありません
    19. 19. 皆さん INT の最大値について ご存じですか?
    20. 20. INT って 32bit だから 40 億とか入るよねー
    21. 21. php > var_dump(0x80000000); float(2147483648)
    22. 22. 恐怖  float
    23. 23. INTの最大値 <ul><li>PHP_INT_SIZE
    24. 24. 32bit : 0x7FFFFFFF
    25. 25. 64bit : 0x7FFFFFFFFFFFFFFF
    26. 26. 頭が 7 なのは符号で 1bit 使うため </li></ul>
    27. 27. そもそもOSのbit数とは何か <ul><li>CPU の 1 命令での演算の単位
    28. 28. int =その CPU での基本の型、つまり 32bit なら 32bit サイズ、 64bit なら 64bit のサイズが入る
    29. 29. 「正確な整数」をその bit 数以上 CPU が演算することはできない </li></ul>
    30. 30. float <ul><li>浮動小数点数
    31. 31. CPU が保持できる数字のうち、一定 bit を近似値(仮数)、残り bit を底上げする値(指数)に割り当てたもの
    32. 32. 仮数の桁を底上げして擬似的に大きな数字に見せるだけなので、仮数の領域以上の値は正確に表現できない </li></ul>
    33. 33. php > var_dump( (0.1+0.7)*10 ); float(8) php > var_dump( (int)( (0.1+0.7)*10 ) ); int(7) ※ 他の言語でもこうなります
    34. 34. floatは危険 <ul><li>計算に誤差が出る </li><ul><li>主に2の累乗から外れた場合 </li></ul><li>整数と同じ感覚で扱っていると、いつのまにか値がずれていることがあるかもしれない
    35. 35. 金額とかを float なんかで扱うとクレームじゃ済まされない! </li></ul>
    36. 36. 大きい数字を使いたい場合 <ul><li>64bitOS を使う
    37. 37. BCMath 関数を使う
    38. 38. PEAR の Math_BigInteger を使う </li></ul>
    39. 39. ちなみに <ul><li>0xFFFFFFFF より大きい値を指定できるようになったのは PHP5.2.1 以降です
    40. 40. PHP5.2.0 以前だと、 float にはならず桁落ちします </li></ul>
    41. 41. お前を float にしてやろうか!
    42. 42. 03 本当は怖い型キャスト
    43. 43. 皆さん型キャストって安易に 使っていませんか?
    44. 44. float ですら危険なのに まだ型キャストの怖さを わかっていないのですか?
    45. 45. まさか E_NOTICE を切って 開発とかしてませんか?
    46. 46. ※ ここまで $a は未定義 php > $a->a = 1; php > var_dump($a); object(stdClass)#1 (1) { [&quot;a&quot;]=> int(1) }
    47. 47. stdClass ってなに!? ってかなんでエラー出ないの!?
    48. 48. きもいPHP <ul><li>未定義変数に -> でメンバを付けると勝手にオブジェクトになる
    49. 49. 未定義変数に [] でアクセスすると勝手に array になる </li><ul><li>これを未定義だと思ってやって実は文字列だったら… </li></ul></ul>
    50. 50. キャストをライブコーディング <ul><li>bool のキャスト= if の判定と同じ
    51. 51. array のキャスト=その値を push した配列が出来上がる
    52. 52. 謎のキャスト unset </li></ul>
    53. 53. 更に怖い型キャスト
    54. 54. sort関数 <ul><li>sort — 配列をソートする
    55. 55. bool sort ( array &$array [, int $sort_flags = SORT_REGULAR ] )
    56. 56. この関数は配列をソートします。この関数が正常に終了すると、 各要素は低位から高位へ並べ替えられます。 </li></ul>
    57. 57. php > $a=array(&quot;1e1&quot;, &quot;1f1&quot;, &quot;9&quot;); php > sort($a); php > var_dump($a); array(3) { [0]=> string(3) &quot;1e1&quot; [1]=> string(3) &quot;1f1&quot; [2]=> string(1) &quot;9&quot; } php > php > $a=array(&quot;9&quot;, &quot;1e1&quot;, &quot;1f1&quot;); php > sort($a); php > var_dump($a); array(3) { [0]=> string(1) &quot;9&quot; [1]=> string(3) &quot;1e1&quot; [2]=> string(3) &quot;1f1&quot; } 引用元: http://d.hatena.ne.jp/hnw/20090227
    58. 58.          ,. -‐'''''&quot;&quot;¨¨¨ ヽ          (. __ _,,,... - ァァフ |           あ…ありのまま 今 起こった事を話すぜ!           |i i|     }!   }} / / |          |l 、 {     j}   /,, ィ // |       『おれは同じ内容の配列をソートしていたと         i|:! ヾ、 _ ノ/ u {:}// ヘ        思ったら違う結果が出力されていた』         | リ u' }   , ノ  _,!V, ハ |        / ´f ト、 _{ ル {, ィ ' eラ  , タ人        な… 何を言ってるのか わからねーと思うが      /'   ヾ | 宀 | {´,)⌒`/ |< ヽト i ゝ        おれも何をされたのかわからなかった…      , ゙  / ) ヽ iL レ   u' |   | ヾlトハ〉      | / _ /  ハ ! ニ⊇  ' / :}   V::::: ヽ        頭がどうにかなりそうだった…     / / 二二二 7'T'' / u'   __ /:::::::/ `ヽ     /'´r   -― 一ァ‐゙T ´   '&quot;´ / :::: / -‐  \    型変換だとか isset だとか    / //   广 ¨´   /'    / ::::: / ´  ̄`ヽ ⌒ヽ    そんなチャチなもんじゃあ 断じてねえ   ノ ' /   ノ :::::` ー - 、 ___ / ::::: / /       ヽ   } _ /`丶  /::::::::::::::::::::::::::  ̄ ` ー -{:::...        イ  もっと恐ろしいものの片鱗を味わったぜ…
    59. 59. どうしてこうなった <ul><li>SORT_REGULAR - 通常通りに項目を比較 ( 型は変更しません )
    60. 60. &quot;1e1&quot;<&quot;1f1&quot; と &quot;1f1&quot;<&quot;9&quot; は文字列による比較
    61. 61. &quot;9&quot; <&quot;1e1&quot; は数字による比較を行ってしまう
    62. 62. 中途半端に型変換された結果がこれだよ! </li></ul>
    63. 63. 傾向と対策 <ul><ul><li>SORT_NUMERIC - 数値的に項目を比較
    64. 64. SORT_STRING - 文字列として項目を比較
    65. 65. 必ず sort 関数ではどちらかを指定しましょう </li></ul></ul>
    66. 66. 迫り来る PHP の 恐怖
    67. 67. 04 本当は怖い日付と時刻 ※ これは PHP とはあまり 関係ありません
    68. 68. みなさん PHP での日付処理は どうやっていますか?
    69. 69. strtotime とか 信頼して使ってませんか?
    70. 70. 1 ヶ月前の日付とか 調べたいなー よし、 strtotime だ!
    71. 71. php > $a = strtotime('2010-03-31'); php > var_dump( date('Y-m-d', strtotime('-1 Month', $a) ) ); string(10) &quot;2010-03-03&quot;
    72. 72. いやああああああああああああああああああああ
    73. 73. どうしてこうなった <ul><li>3 月 31 日の 1 ヶ月前= 2 月 31 日
    74. 74. 2 月 31 日= 2 月 28 日+ 3 日= 3 月 3 日 </li></ul>
    75. 75. strtotime が そこまで気の利いた関数だと 思ったか!!!!!
    76. 76. 対策 <ul><li>mktime を使いましょう
    77. 77. PEAR::Date を使いましょう
    78. 78. PHP5.2 以上なら DateTime オブジェクトを使いましょう
    79. 79. もう日付を数値で扱うのはやめましょう!!! </li></ul>
    80. 80. 2038年問題 <ul><li>INT の最大値= 0x7FFFFFFF
    81. 81. 数値の日付= 1970 年 1 月 1 日 0 時 0 分 0 秒 (GMT) からの秒数 </li><ul><li>php > var_dump(date('Y-m-d H:i:s', 0));
    82. 82. string(19) &quot;1970-01-01 09:00:00&quot;
    83. 83. 9:00 になっているのは JST だから </li></ul></ul>
    84. 84. php > var_dump(date('Y-m-d H:i:s', 0x7FFFFFFF)); String(19) &quot;2038-01-19 12:14:07&quot; php > var_dump(date('Y-m-d H:i:s', 0x7FFFFFFF+1)); string(19) &quot;1901-12-14 05:45:52&quot;
    85. 85. これも対策 <ul><li>64bitOS 使っていれば起きない
    86. 86. PEAR::Date を使いましょう
    87. 87. PHP5.2 以降なら DateTime オブジェクトを使いましょう
    88. 88. もう日付を(略 </li></ul>
    89. 89. ちなみに <ul><li>64bit 環境でも、例えば DB に日付を INT で保存していたりすると回避できません
    90. 90. どっかの CMS とか…
    91. 91. 必ず DB の組み込みの日付型を使いましょう </li></ul>
    92. 92. PHP の怖さが わかったか!
    93. 93. PHP なんてやめてしまえ!
    94. 94. うそですごめんなさい
    95. 95. おわり

    ×